Adds types for bundled visualizations & improves data extractor types.

This commit is contained in:
Henning Dieterichs
2020-08-22 15:40:24 +02:00
parent 62415f1775
commit 1dd0349483
17 changed files with 448 additions and 331 deletions

View File

@@ -1,7 +1,7 @@
{
"name": "@hediet/debug-visualizer-data-extraction",
"description": "A library that helps implementing data extractors for the Debug Visualizer VS Code extension.",
"version": "0.12.0",
"version": "0.13.0",
"main": "dist/index.js",
"types": "dist/index.d.ts",
"author": {

View File

@@ -1,122 +1,256 @@
import { ExtractedData } from "./DataExtractionResult";
// This file was created automatically. Do not edit it manually!
export type CommonDataType =
| CommonDataTypes.Text
| CommonDataTypes.Svg
| CommonDataTypes.Html
| CommonDataTypes.DotGraph
| CommonDataTypes.Tree
| CommonDataTypes.Ast
| CommonDataTypes.Graph
| CommonDataTypes.Plotly
| CommonDataTypes.Grid;
export type KnownVisualizationData =
| TreeVisualizationData
| AstTreeVisualizationData
| GraphvizDotVisualizationData
| GraphVisualizationData
| GraphVisualizationData
| GridVisualizationData
| ImageVisualizationData
| MonacoTextVisualizationData
| TableVisualizationData
| PlotlyVisualizationData
| SimpleTextVisualizationData
| SvgVisualizationData;
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;
}
export type TreeVisualizationData = {
kind: {
tree: true;
};
root: TreeNode;
};
type Narrow<T, TKind> = T extends TKind ? T : never;
export module CommonDataTypes {
export interface Text {
kind: { text: true };
text: string;
mimeType?: string;
fileName?: string;
}
export interface Graph {
kind: { graph: true };
nodes: NodeGraphData[];
edges: EdgeGraphData[];
}
export interface Svg extends Text {
kind: { text: true; svg: true };
}
export interface Html extends Text {
kind: { text: true; html: true };
}
export interface DotGraph extends Text {
kind: { text: true; dotGraph: true };
}
export interface Tree<TData = unknown> {
kind: { tree: true };
root: TreeNode<TData>;
}
export interface Grid {
kind: { array: true };
columnLabels?: { label?: string }[];
rows: {
label?: string;
columns: {
content?: string;
tag?: string;
color?: string;
}[];
}[];
markers?: {
id: string;
row: number;
column: number;
rows?: number;
columns?: number;
label?: string;
color?: string;
}[];
}
export interface Ast
extends Tree<{
position: number;
length: number;
}>,
Text {
kind: { text: true; tree: true; ast: true };
}
export interface Plotly {
kind: { plotly: true };
data: Partial<Plotly.Data>[];
}
}
export interface TreeNode<TExtraData> {
name: string;
children: TreeNode<TExtraData>[];
data: TExtraData;
id?: string;
value?: string;
emphasizedValue?: string;
export type TreeNode = {
/**
* The children of this tree-node
*/
children: TreeNode[];
/**
* The parts that make up the text of this item
*/
items: TreeNodeItem[];
/**
* If a node is selected, the concatenation of all segment values from root to the selected node is shown to the user.
*/
segment?: string;
/**
* Marked nodes are highlighted and scrolled into view on every visualization update.
*/
isMarked?: boolean;
}
};
export interface NodeGraphData {
export type TreeNodeItem = {
/**
* The text to show
*/
text: string;
/**
* The style of the text
*/
emphasis?: "style1" | "style2" | "style3" | string;
};
export type AstTreeVisualizationData = {
kind: {
ast: true;
tree: true;
text: true;
};
root: AstTreeNode;
text: string;
fileName?: string;
};
export type AstTreeNode = {
children: AstTreeNode[];
items: AstTreeNodeItem[];
segment?: string;
isMarked?: boolean;
span: {
start: number;
length: number;
};
};
export type AstTreeNodeItem = {
text: string;
emphasis?: "style1" | "style2" | "style3" | string;
};
export type GraphvizDotVisualizationData = {
kind: {
dotGraph: true;
};
text: string;
};
export type GraphVisualizationData = {
kind: {
graph: true;
};
nodes: GraphNode[];
edges: GraphEdge[];
};
export type GraphNode = {
id: string;
label?: string;
color?: string;
shape?: "ellipse" | "box";
}
};
export interface EdgeGraphData {
export type GraphEdge = {
from: string;
to: string;
label?: string;
id?: string;
color?: string;
dashes?: boolean;
}
};
export type GridVisualizationData = {
kind: {
grid: true;
};
columnLabels?: {
label?: string;
}[];
rows: {
label?: string;
columns: {
content?: string;
/**
* A value to identify this cell. Should be unique.
*/
tag?: string;
color?: string;
}[];
}[];
markers?: {
id: string;
row: number;
column: number;
rows?: number;
columns?: number;
label?: string;
color?: string;
}[];
};
export type ImageVisualizationData = {
kind: {
imagePng: true;
};
/**
* The base 64 encoded PNG representation of the image
*/
base64Data: string;
};
export type MonacoTextVisualizationData = {
kind: {
text: true;
};
/**
* The text to show
*/
text: string;
/**
* An optional filename that might be used for chosing a syntax highlighter
*/
fileName?: string;
};
export type TableVisualizationData = {
kind: {
table: true;
};
/**
* An array of objects. The properties of the objects are used as columns.
*/
rows: {}[];
};
export type PlotlyVisualizationData = {
kind: {
plotly: true;
};
/**
* Expecting Plotly.Data[] (https://github.com/DefinitelyTyped/DefinitelyTyped/blob/795ce172038dbafcb9cba030d637d733a7eea19c/types/plotly.js/index.d.ts#L1036)
*/
data: {
text?: string | string[];
xaxis?: string;
yaxis?: string;
x?: (string | number | null)[] | (string | number | null)[][];
y?: (string | number | null)[] | (string | number | null)[][];
z?: (string | number | null)[] | (string | number | null)[][];
type?:
| "bar"
| "box"
| "candlestick"
| "choropleth"
| "contour"
| "heatmap"
| "histogram"
| "indicator"
| "mesh3d"
| "ohlc"
| "parcoords"
| "pie"
| "pointcloud"
| "scatter"
| "scatter3d"
| "scattergeo"
| "scattergl"
| "scatterpolar"
| "scatterternary"
| "sunburst"
| "surface"
| "treemap"
| "waterfall"
| "funnel"
| "funnelarea"
| "scattermapbox";
mode?:
| "lines"
| "markers"
| "text"
| "lines+markers"
| "text+markers"
| "text+lines"
| "text+lines+markers"
| "none"
| "gauge"
| "number"
| "delta"
| "number+delta"
| "gauge+number"
| "gauge+number+delta"
| "gauge+delta";
}[];
/**
* Expecting Partial<Plotly.Layout> (https://github.com/DefinitelyTyped/DefinitelyTyped/blob/795ce172038dbafcb9cba030d637d733a7eea19c/types/plotly.js/index.d.ts#L329)
*/
layout?: {
title?: string;
};
};
export type SimpleTextVisualizationData = {
kind: {
text: true;
};
text: string;
};
export type SvgVisualizationData = {
kind: {
svg: true;
};
/**
* The svg content
*/
text: string;
};

View File

@@ -1,27 +1,27 @@
export type DataExtractionResult = {
data: ExtractedData;
export interface DataExtractionResult {
data: VisualizationData;
usedExtractor: DataExtractorInfo;
availableExtractors: DataExtractorInfo[];
};
}
/**
* Instances must be valid json values.
*/
export type ExtractedData = {
export interface VisualizationData {
kind: Record<string, true>;
};
}
export type DataExtractorInfo = {
export interface DataExtractorInfo {
id: DataExtractorId;
name: string;
priority: number;
};
}
export type DataExtractorId = {
__brand: "DataExtractorId";
} & string;
export function isExtractedData(val: unknown): val is ExtractedData {
export function isVisualizationData(val: unknown): val is VisualizationData {
if (typeof val !== "object" || !val || !("kind" in val)) {
return false;
}

View File

@@ -1,5 +1,5 @@
import {
ExtractedData,
VisualizationData,
DataExtractionResult,
} from "../../DataExtractionResult";
@@ -7,14 +7,12 @@ export interface DataExtractorApi {
/**
* Registers a single extractor.
*/
registerExtractor<TExtractedData extends ExtractedData>(
extractor: DataExtractor<TExtractedData>
): void;
registerExtractor(extractor: DataExtractor): void;
/**
* Registers multiple extractors.
*/
registerExtractors(extractors: DataExtractor<ExtractedData>[]): void;
registerExtractors(extractors: DataExtractor[]): void;
/**
* Extracts data from the result of `valueFn`.
@@ -46,23 +44,23 @@ export interface JSONString<T> extends String {
__brand: { json: T };
}
export interface DataExtractor<T extends ExtractedData> {
export interface DataExtractor {
/**
* Must be unique among all data extractors.
*/
id: string;
getExtractions(
data: unknown,
extractionCollector: ExtractionCollector<T>,
extractionCollector: ExtractionCollector,
context: DataExtractorContext
): void;
}
export interface ExtractionCollector<T extends ExtractedData> {
export interface ExtractionCollector {
/**
* Suggests a possible extraction.
*/
addExtraction(extraction: DataExtraction<T>): void;
addExtraction(extraction: DataExtraction): void;
}
export interface DataExtractorContext {
@@ -72,7 +70,7 @@ export interface DataExtractorContext {
evalFn: <TEval>(expression: string) => TEval;
}
export interface DataExtraction<TData extends ExtractedData> {
export interface DataExtraction {
/**
* Higher priorities are preferred.
*/
@@ -87,5 +85,5 @@ export interface DataExtraction<TData extends ExtractedData> {
* A user friendly name of this extraction.
*/
name: string;
extractData(): TData;
extractData(): VisualizationData;
}

View File

@@ -6,7 +6,10 @@ import {
DataExtraction,
ExtractionCollector,
} from "./DataExtractorApi";
import { ExtractedData, DataExtractorInfo } from "../../DataExtractionResult";
import {
VisualizationData,
DataExtractorInfo,
} from "../../DataExtractionResult";
import { registerDefaultExtractors } from "./default-extractors";
/**
@@ -15,24 +18,17 @@ import { registerDefaultExtractors } from "./default-extractors";
export class DataExtractorApiImpl implements DataExtractorApi {
public static lastEvalFn: (<T>(expression: string) => T) | undefined;
private readonly extractors = new Map<
string,
DataExtractor<ExtractedData>
>();
private readonly extractors = new Map<string, DataExtractor>();
private toJson<TData>(data: TData): JSONString<TData> {
return JSON.stringify(data) as any;
}
public registerExtractor<TExtractedData extends ExtractedData>(
extractor: DataExtractor<TExtractedData>
): void {
public registerExtractor(extractor: DataExtractor): void {
this.extractors.set(extractor.id, extractor);
}
public registerExtractors(
extractors: DataExtractor<ExtractedData>[]
): void {
public registerExtractors(extractors: DataExtractor[]): void {
for (const e of extractors) {
this.registerExtractor(e);
}
@@ -43,8 +39,8 @@ export class DataExtractorApiImpl implements DataExtractorApi {
evalFn: <T>(expression: string) => T,
preferredDataExtractorId: string | undefined
): JSONString<DataResult> {
const extractions = new Array<DataExtraction<ExtractedData>>();
const extractionCollector: ExtractionCollector<ExtractedData> = {
const extractions = new Array<DataExtraction>();
const extractionCollector: ExtractionCollector = {
addExtraction(extraction) {
extractions.push(extraction);
},
@@ -72,9 +68,7 @@ export class DataExtractorApiImpl implements DataExtractorApi {
}
}
function mapExtractor(
e: DataExtraction<ExtractedData>
): DataExtractorInfo {
function mapExtractor(e: DataExtraction): DataExtractorInfo {
return {
id: e.id as any,
name: e.name,

View File

@@ -1,18 +1,18 @@
import { ExtractedData, isExtractedData } from "../../../DataExtractionResult";
import { isVisualizationData } from "../../../DataExtractionResult";
import {
DataExtractor,
ExtractionCollector,
DataExtractorContext,
} from "../..";
export class AsIsDataExtractor implements DataExtractor<ExtractedData> {
export class AsIsDataExtractor implements DataExtractor {
readonly id = "as-is";
getExtractions(
data: unknown,
extractionCollector: ExtractionCollector<ExtractedData>,
extractionCollector: ExtractionCollector,
context: DataExtractorContext
): void {
if (!isExtractedData(data)) {
if (!isVisualizationData(data)) {
return;
}

View File

@@ -1,32 +1,33 @@
import { ExtractedData } from "../../../DataExtractionResult";
import { VisualizationData } from "../../../DataExtractionResult";
import {
DataExtractor,
ExtractionCollector,
DataExtractorContext,
} from "../DataExtractorApi";
export class GetDebugVisualizationDataExtractor
implements DataExtractor<ExtractedData> {
readonly id = "get-debug-visualization";
export class GetVisualizationDataExtractor implements DataExtractor {
readonly id = "get-visualization-data";
getExtractions(
data: unknown,
collector: ExtractionCollector<ExtractedData>,
collector: ExtractionCollector,
context: DataExtractorContext
): void {
if (
typeof data !== "object" ||
!data ||
!("getDebugVisualization" in data)
) {
if (typeof data !== "object" || !data) {
return;
}
const getVisualizationData = (data as any)
.getVisualizationData as Function;
if (typeof getVisualizationData !== "function") {
return;
}
collector.addExtraction({
id: this.id,
name: "Use Method 'getDebugVisualization'",
name: "Use Method 'getVisualizationData'",
priority: 600,
extractData() {
return (data as any).getDebugVisualization();
return getVisualizationData.apply(data);
},
});
}

View File

@@ -1,16 +1,16 @@
import { ExtractedData } from "../../../DataExtractionResult";
import {
DataExtractor,
ExtractionCollector,
DataExtractorContext,
} from "../..";
import { CommonDataTypes } from "../../../CommonDataTypes";
import { GridVisualizationData } from "../../../CommonDataTypes";
import { expect } from "../../../util";
export class GridExtractor implements DataExtractor<ExtractedData> {
export class GridExtractor implements DataExtractor {
readonly id = "grid";
getExtractions(
data: unknown,
extractionCollector: ExtractionCollector<ExtractedData>,
extractionCollector: ExtractionCollector,
context: DataExtractorContext
): void {
if (!Array.isArray(data)) {
@@ -21,12 +21,11 @@ export class GridExtractor implements DataExtractor<ExtractedData> {
id: this.id,
name: "Array As Grid",
priority: 500,
extractData(): CommonDataTypes.Grid {
return {
kind: { array: true },
extractData: () =>
expect<GridVisualizationData>({
kind: { grid: true },
rows: [{ columns: data.map(d => ({ tag: d })) }],
};
},
}),
});
}
}

View File

@@ -1,4 +1,4 @@
import { ExtractedData } from "../../../DataExtractionResult";
import { VisualizationData } from "../../../DataExtractionResult";
import {
DataExtractor,
ExtractionCollector,
@@ -6,12 +6,12 @@ import {
} from "../DataExtractorApi";
import { createGraph, CreateGraphEdge } from "../../helpers";
export class ObjectGraphExtractor implements DataExtractor<ExtractedData> {
export class ObjectGraphExtractor implements DataExtractor {
readonly id = "object-graph";
getExtractions(
data: unknown,
collector: ExtractionCollector<ExtractedData>,
collector: ExtractionCollector,
context: DataExtractorContext
): void {
function isObject(val: unknown): val is object {

View File

@@ -1,17 +1,17 @@
import { ExtractedData } from "../../../DataExtractionResult";
import { PlotlyVisualizationData } from "../../../CommonDataTypes";
import { expect } from "../../../util";
import {
DataExtractor,
ExtractionCollector,
DataExtractorContext,
} from "../DataExtractorApi";
import { CommonDataTypes } from "../../../CommonDataTypes";
export class PlotDataExtractor implements DataExtractor<ExtractedData> {
export class PlotlyDataExtractor implements DataExtractor {
readonly id = "plot";
getExtractions(
data: unknown,
collector: ExtractionCollector<ExtractedData>,
collector: ExtractionCollector,
context: DataExtractorContext
): void {
if (!Array.isArray(data)) {
@@ -25,14 +25,13 @@ export class PlotDataExtractor implements DataExtractor<ExtractedData> {
id: "plot-y",
name: "Plot as y-Values",
priority: 1001,
extractData() {
return {
extractData: () =>
expect<PlotlyVisualizationData>({
kind: {
plotly: true,
},
data: [{ y: data }],
} as CommonDataTypes.Plotly;
},
}),
});
}
}

View File

@@ -1,16 +1,17 @@
import { ExtractedData } from "../../../DataExtractionResult";
import { MonacoTextVisualizationData } from "../../../CommonDataTypes";
import { expect } from "../../../util";
import {
DataExtractor,
ExtractionCollector,
DataExtractorContext,
} from "../DataExtractorApi";
export class ToStringDataExtractor implements DataExtractor<ExtractedData> {
export class ToStringDataExtractor implements DataExtractor {
readonly id = "to-string";
getExtractions(
data: unknown,
collector: ExtractionCollector<ExtractedData>,
collector: ExtractionCollector,
context: DataExtractorContext
): void {
collector.addExtraction({
@@ -18,12 +19,12 @@ export class ToStringDataExtractor implements DataExtractor<ExtractedData> {
name: "To String",
priority: 100,
extractData() {
return {
return expect<MonacoTextVisualizationData>({
kind: {
text: true,
},
text: "" + data,
};
});
},
});
}

View File

@@ -1,42 +1,19 @@
import * as ts from "typescript"; // Only compile-time import!
import { AstTreeNode } from "../../..";
import { AstTreeVisualizationData } from "../../../CommonDataTypes";
import { expect } from "../../../util";
import {
DataExtractor,
ExtractionCollector,
DataExtractorContext,
} from "../DataExtractorApi";
type AstType = {
kind: {
tree: true;
ast: true;
text: true;
};
root: TreeNode;
text: string;
};
type TreeNode = {
children: TreeNode[];
items: TreeNodeItem[];
segment?: string;
isMarked?: boolean;
span: {
start: number;
length: number;
};
};
type TreeNodeItem = {
text: string;
emphasis?: "style1" | "style2" | "style3";
};
export class TypeScriptAstDataExtractor implements DataExtractor<AstType> {
export class TypeScriptAstDataExtractor implements DataExtractor {
readonly id = "typescript-ast";
getExtractions(
data: unknown,
collector: ExtractionCollector<AstType>,
collector: ExtractionCollector,
{ evalFn }: DataExtractorContext
): void {
if (!data) {
@@ -63,116 +40,21 @@ export class TypeScriptAstDataExtractor implements DataExtractor<AstType> {
return;
}
function findKey(value: any, object: any): string | null {
for (var key in object) {
if (key.startsWith("_")) continue;
var member = object[key];
if (member === value) return key;
if (Array.isArray(member) && member.indexOf(value) !== -1) {
return key;
}
}
return null;
}
function getChildren(node: ts.Node): ts.Node[] {
const result = new Array<ts.Node>();
tsApi.forEachChild(node, n => {
result.push(n);
});
return result;
}
function toTreeNode(
node: ts.Node,
memberName: string,
marked: Set<ts.Node>,
emphasizedValueFn: (node: ts.Node) => string | undefined
): TreeNode {
const name = tsApi.SyntaxKind[node.kind];
const children = getChildren(node)
.map((childNode, idx) => {
let parentPropertyName = findKey(childNode, node) || "";
if (childNode.kind == tsApi.SyntaxKind.SyntaxList) {
const children = getChildren(childNode);
children.some(c => {
parentPropertyName = findKey(c, node) || "";
return !!parentPropertyName;
});
if (children.length === 0) return null!;
}
if (node.kind == tsApi.SyntaxKind.SyntaxList) {
parentPropertyName = "" + idx;
}
return toTreeNode(
childNode,
parentPropertyName,
marked,
emphasizedValueFn
);
})
.filter(c => c !== null);
let value: string | undefined = undefined;
if (tsApi.isIdentifier(node)) {
value = node.text || (node.escapedText as string);
} else if (tsApi.isLiteralExpression(node)) {
value = node.text;
}
return {
items: [
{ text: memberName, emphasis: "style1" },
{ text: name },
],
children: children,
span: {
length: node.end - node.pos,
start: node.pos,
},
//emphasizedValue: emphasizedValueFn(node),
isMarked: marked.has(node),
//value,
};
}
function isNode(node: unknown): node is ts.Node {
return (
typeof node === "object" &&
node !== null &&
(tsApi.isToken(node as any) || (tsApi as any).isNode(node))
);
}
function getSourceFile(node: ts.Node | any): ts.SourceFile {
if (!node) {
throw new Error("Detached node");
}
if (tsApi.isSourceFile(node)) {
return node;
}
if (!("getSourceFile" in node)) {
return getSourceFile(node.parent);
}
return node.getSourceFile();
}
const helper = new Helper(tsApi);
let rootSourceFile: ts.SourceFile | undefined = undefined;
let rootNode: ts.Node | undefined = undefined;
let marked: Set<ts.Node>;
let fn: (n: ts.Node) => string | undefined = (n: ts.Node) => undefined;
if (Array.isArray(data) && data.every(isNode) && data.length > 0) {
rootSourceFile = getSourceFile(data[0] as ts.Node);
if (
Array.isArray(data) &&
data.every(helper.isNode) &&
data.length > 0
) {
rootSourceFile = helper.getSourceFile(data[0] as ts.Node);
marked = new Set(data);
} else if (isNode(data)) {
rootSourceFile = getSourceFile(data);
} else if (helper.isNode(data)) {
rootSourceFile = helper.getSourceFile(data);
marked = new Set([data]);
} else if (typeof data === "object" && data) {
marked = new Set();
@@ -187,15 +69,18 @@ export class TypeScriptAstDataExtractor implements DataExtractor<AstType> {
rootNode = item;
}
let nodes: Array<ts.Node>;
if (isNode(item)) {
if (helper.isNode(item)) {
nodes = [item];
} else if (Array.isArray(item) && item.every(isNode)) {
} else if (
Array.isArray(item) &&
item.every(helper.isNode)
) {
nodes = item;
} else {
return;
}
if (nodes.length > 0 && !rootSourceFile) {
rootSourceFile = getSourceFile(nodes[0]);
rootSourceFile = helper.getSourceFile(nodes[0]);
}
for (const n of nodes) {
marked.add(n);
@@ -217,9 +102,9 @@ export class TypeScriptAstDataExtractor implements DataExtractor<AstType> {
name: "TypeScript AST",
priority: 1000,
extractData() {
return {
return expect<AstTreeVisualizationData>({
kind: { text: true, tree: true, ast: true },
root: toTreeNode(
root: helper.toTreeNode(
rootNode || finalRootSourceFile,
"root",
marked,
@@ -227,8 +112,111 @@ export class TypeScriptAstDataExtractor implements DataExtractor<AstType> {
),
text: finalRootSourceFile.text,
fileName: "index.ts",
};
});
},
});
}
}
class Helper {
constructor(private readonly tsApi: typeof ts) {}
findKey(value: any, object: any): string | null {
for (var key in object) {
if (key.startsWith("_")) continue;
var member = object[key];
if (member === value) return key;
if (Array.isArray(member) && member.indexOf(value) !== -1) {
return key;
}
}
return null;
}
getChildren(node: ts.Node): ts.Node[] {
const result = new Array<ts.Node>();
this.tsApi.forEachChild(node, n => {
result.push(n);
});
return result;
}
toTreeNode(
node: ts.Node,
memberName: string,
marked: Set<ts.Node>,
emphasizedValueFn: (node: ts.Node) => string | undefined
): AstTreeNode {
const name = this.tsApi.SyntaxKind[node.kind];
const children = this.getChildren(node)
.map((childNode, idx) => {
let parentPropertyName = this.findKey(childNode, node) || "";
if (childNode.kind == this.tsApi.SyntaxKind.SyntaxList) {
const children = this.getChildren(childNode);
children.some(c => {
parentPropertyName = this.findKey(c, node) || "";
return !!parentPropertyName;
});
if (children.length === 0) return null!;
}
if (node.kind == this.tsApi.SyntaxKind.SyntaxList) {
parentPropertyName = "" + idx;
}
return this.toTreeNode(
childNode,
parentPropertyName,
marked,
emphasizedValueFn
);
})
.filter(c => c !== null);
let value: string | undefined = undefined;
if (this.tsApi.isIdentifier(node)) {
value = node.text || (node.escapedText as string);
} else if (this.tsApi.isLiteralExpression(node)) {
value = node.text;
}
return {
items: [{ text: memberName, emphasis: "style1" }, { text: name }],
children: children,
span: {
length: node.end - node.pos,
start: node.pos,
},
//emphasizedValue: emphasizedValueFn(node),
isMarked: marked.has(node),
//value,
};
}
isNode = (node: unknown): node is ts.Node => {
return (
typeof node === "object" &&
node !== null &&
(this.tsApi.isToken(node as any) ||
(this.tsApi as any).isNode(node))
);
};
getSourceFile(node: ts.Node | any): ts.SourceFile {
if (!node) {
throw new Error("Detached node");
}
if (this.tsApi.isSourceFile(node)) {
return node;
}
if (!("getSourceFile" in node)) {
return this.getSourceFile(node.parent);
}
return node.getSourceFile();
}
}

View File

@@ -1,9 +1,9 @@
import { DataExtractorApi } from "../DataExtractorApi";
import { TypeScriptAstDataExtractor } from "./TypeScriptDataExtractors";
import { AsIsDataExtractor } from "./AsIsDataExtractor";
import { GetDebugVisualizationDataExtractor } from "./GetDebugVisualizationDataExtractor";
import { GetVisualizationDataExtractor } from "./GetDebugVisualizationDataExtractor";
import { ToStringDataExtractor } from "./ToStringExtractor";
import { PlotDataExtractor } from "./PlotlyDataExtractor";
import { PlotlyDataExtractor } from "./PlotlyDataExtractor";
import { ObjectGraphExtractor } from "./ObjectGraphExtractor";
import { getDataExtractorApi } from "../injection";
import { GridExtractor } from "./GridExtractor";
@@ -18,9 +18,9 @@ export function registerDefaultExtractors(
for (const item of [
new TypeScriptAstDataExtractor(),
new AsIsDataExtractor(),
new GetDebugVisualizationDataExtractor(),
new GetVisualizationDataExtractor(),
new ToStringDataExtractor(),
new PlotDataExtractor(),
new PlotlyDataExtractor(),
new ObjectGraphExtractor(),
new GridExtractor(),
]) {

View File

@@ -0,0 +1,3 @@
export function expect<T>(data: T): T {
return data;
}

View File

@@ -1,6 +1,6 @@
import {
DataExtractionResult,
isExtractedData,
isVisualizationData,
} from "@hediet/debug-visualizer-data-extraction";
import { FormattedMessage } from "../../webviewContract";
@@ -40,7 +40,7 @@ export function parseEvaluationResultFromGenericDebugAdapter(
// result is now { kind: { ... }, text: "some\ntext" }
}
if (!isExtractedData(resultObj)) {
if (!isVisualizationData(resultObj)) {
return {
kind: "error",
message: {

View File

@@ -4,7 +4,7 @@
"license": "GPL-3.0",
"scripts": {
"dev": "webpack-dev-server --hot",
"build": "webpack"
"build": "node --max_old_space_size=4096 ../node_modules/webpack/bin/webpack.js --mode production"
},
"main": "./index.js",
"dependencies": {

View File

@@ -9,7 +9,7 @@ import { ConsoleRpcLogger } from "@hediet/typed-json-rpc";
import { observable, action, computed, when, runInAction } from "mobx";
import {
DataExtractorId,
ExtractedData,
VisualizationData,
} from "@hediet/debug-visualizer-data-extraction";
import "@hediet/visualization-bundle";
import {
@@ -41,7 +41,7 @@ export class Model {
@observable.ref state:
| DataExtractionState
| { kind: "noExpression" }
| { kind: "visualizationError"; data: ExtractedData } = {
| { kind: "visualizationError"; data: VisualizationData } = {
kind: "noExpression",
};
@@ -62,7 +62,7 @@ export class Model {
}
@action
public setVisualizationError(data: ExtractedData) {
public setVisualizationError(data: VisualizationData) {
this.state = { kind: "visualizationError", data: data };
}