Implements some visualizers.

This commit is contained in:
Henning Dieterichs
2019-08-02 11:53:17 +02:00
parent 99a0f854a3
commit 26306b68f8
23 changed files with 621 additions and 279 deletions

View File

@@ -1,5 +1,28 @@
import { ExtractedData } from "./DataExtractionResult";
export function isCommonDataType<T>(
data: ExtractedData,
kind: T
): data is Narrow<CommonDataType, { kind: T }> {
for (const key of Object.keys(kind)) {
if (!(key in data.kind)) {
return false;
}
}
return true;
}
type Narrow<T, TKind> = T extends TKind ? T : never;
export type CommonDataType =
| CommonDataTypes.Text
| CommonDataTypes.Svg
| CommonDataTypes.Html
| CommonDataTypes.DotGraph
| CommonDataTypes.TreeNodeData
| CommonDataTypes.AstData
| CommonDataTypes.GraphData;
export module CommonDataTypes {
export interface Text extends ExtractedData {
kind: { text: true };
@@ -8,6 +31,12 @@ export module CommonDataTypes {
fileType?: string;
}
export interface GraphData {
kind: { graph: true };
nodes: { id: string; label: string }[];
edges: { from: string; to: string; label: string }[];
}
export interface Svg extends Text {
kind: { text: true; svg: true };
text: string;

View File

@@ -0,0 +1,30 @@
import { ExtractedData } from "../../DataExtractionResult";
import { DataExtractor, ExtractionCollector } from "..";
export class AsIsDataExtractor implements DataExtractor<ExtractedData> {
readonly id = "as-is";
getExtractions(
data: unknown,
extractionCollector: ExtractionCollector<ExtractedData>,
evalFn: <TEval>(expression: string) => TEval
): void {
if (typeof data === "object" && data && "kind" in data) {
const obj = data as any;
if (typeof obj.kind === "object" && obj.kind) {
const areAllTrue = Object.values(obj.kind).every(
val => val === true
);
if (areAllTrue) {
extractionCollector.addExtraction({
id: "as-is",
name: "As Is",
priority: 100,
extractData() {
return obj;
},
});
}
}
}
}
}

View File

@@ -11,7 +11,7 @@ export class TypeScriptAstDataExtractor
collector: ExtractionCollector<CommonDataTypes.AstData>,
evalFn: <TEval>(expression: string) => TEval
): void {
if (typeof data !== "object" || data === undefined) {
if (!data) {
return;
}
@@ -39,7 +39,7 @@ export class TypeScriptAstDataExtractor
function toTreeNode(
node: ts.Node,
memberName: string,
marked: ts.Node
marked: Set<ts.Node>
): CommonDataTypes.AstData["root"] {
const name = tsApi.SyntaxKind[node.kind];
const children = node
@@ -78,19 +78,28 @@ export class TypeScriptAstDataExtractor
length: 0,
position: 0,
},
isMarked: node === marked,
isMarked: marked.has(node),
value,
// startPos: node.pos,
// endPos: node.end
};
}
if ((tsApi as any).isNode(data)) {
let root = data as ts.Node;
const marked = root;
while (root.parent) {
root = root.parent;
function isNode(node: unknown): node is ts.Node {
return typeof node === "object" && (tsApi as any).isNode(node);
}
if (isNode(data) || (Array.isArray(data) && data.every(isNode))) {
let root: ts.SourceFile;
let marked: Set<ts.Node>;
if (Array.isArray(data)) {
root = (data[0] as ts.Node).getSourceFile();
marked = new Set(data);
} else {
root = data.getSourceFile();
marked = new Set([data]);
}
collector.addExtraction({
id: "ts-ast",
name: "TypeScript AST",
@@ -99,7 +108,7 @@ export class TypeScriptAstDataExtractor
return {
kind: { text: true, tree: true, ast: true },
root: toTreeNode(root, "root", marked),
text: root.getSourceFile().text,
text: root.text,
fileType: "ts",
};
},

View File

@@ -1,8 +1,15 @@
import { getDataExtractorApi } from "../DataExtractorApi";
import { TypeScriptAstDataExtractor } from "./TypeScriptDataExtractors";
import { AsIsDataExtractor } from "./AsIsDataExtractor";
export * from "./TypeScriptDataExtractors";
export function registerAll() {
getDataExtractorApi().registerExtractor(new TypeScriptAstDataExtractor());
const api = getDataExtractorApi();
for (const item of [
new TypeScriptAstDataExtractor(),
new AsIsDataExtractor(),
]) {
api.registerExtractor(item);
}
}