dot-language-support 1.7.0 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/workflows/CD.yml +3 -3
- package/.github/workflows/CI.yml +2 -2
- package/README.md +5 -4
- package/jest.config.mjs +19 -0
- package/lib/{binder.d.ts → cjs/binder.d.ts} +1 -1
- package/lib/{binder.js → cjs/binder.js} +34 -34
- package/lib/{checker.d.ts → cjs/checker.d.ts} +1 -1
- package/lib/{checker.js → cjs/checker.js} +28 -28
- package/lib/{core.d.ts → cjs/core.d.ts} +0 -0
- package/lib/{core.js → cjs/core.js} +0 -0
- package/lib/{error.d.ts → cjs/error.d.ts} +1 -1
- package/lib/{error.js → cjs/error.js} +0 -0
- package/lib/cjs/index.d.ts +5 -0
- package/lib/{index.js → cjs/index.js} +5 -5
- package/lib/{parser.d.ts → cjs/parser.d.ts} +1 -1
- package/lib/{parser.js → cjs/parser.js} +11 -11
- package/lib/{scanner.d.ts → cjs/scanner.d.ts} +1 -1
- package/lib/{scanner.js → cjs/scanner.js} +67 -67
- package/lib/{service → cjs/service}/codeAction.d.ts +2 -2
- package/lib/{service → cjs/service}/codeAction.js +34 -34
- package/lib/{service → cjs/service}/colorProvider.d.ts +3 -3
- package/lib/{service → cjs/service}/colorProvider.js +3 -3
- package/lib/{service → cjs/service}/command/ChangeAllOtherEdgeOpsAndFixGraphCommand.d.ts +3 -3
- package/lib/{service → cjs/service}/command/ChangeAllOtherEdgeOpsAndFixGraphCommand.js +6 -6
- package/lib/{service → cjs/service}/command/ChangeEdgeOpCommand.d.ts +3 -3
- package/lib/{service → cjs/service}/command/ChangeEdgeOpCommand.js +3 -3
- package/lib/{service → cjs/service}/command/ConsolidateDescendantsCommand.d.ts +3 -3
- package/lib/{service → cjs/service}/command/ConsolidateDescendantsCommand.js +7 -7
- package/lib/{service → cjs/service}/command/RemoveSemicolons.d.ts +3 -3
- package/lib/{service → cjs/service}/command/RemoveSemicolons.js +4 -4
- package/lib/{service → cjs/service}/command/common.d.ts +2 -2
- package/lib/{service → cjs/service}/command/common.js +6 -6
- package/lib/{service → cjs/service}/completion.d.ts +2 -2
- package/lib/{service → cjs/service}/completion.js +25 -25
- package/lib/{service → cjs/service}/hover.d.ts +2 -2
- package/lib/{service → cjs/service}/hover.js +38 -38
- package/lib/{service → cjs/service}/languageFacts.d.ts +0 -0
- package/lib/{service → cjs/service}/languageFacts.js +0 -0
- package/lib/{service → cjs/service}/polyfill.d.ts +0 -0
- package/lib/{service → cjs/service}/polyfill.js +0 -0
- package/lib/{service → cjs/service}/reference.d.ts +2 -2
- package/lib/{service → cjs/service}/reference.js +9 -9
- package/lib/{service → cjs/service}/rename.d.ts +2 -2
- package/lib/{service → cjs/service}/rename.js +11 -11
- package/lib/{service → cjs/service}/service.d.ts +2 -2
- package/lib/cjs/service/service.js +39 -0
- package/lib/{service → cjs/service}/util.d.ts +2 -2
- package/lib/{service → cjs/service}/util.js +5 -5
- package/lib/{service → cjs/service}/validation.d.ts +2 -2
- package/lib/{service → cjs/service}/validation.js +3 -3
- package/lib/cjs/tester.d.ts +1 -0
- package/lib/cjs/tester.js +23 -0
- package/lib/{types.d.ts → cjs/types.d.ts} +0 -0
- package/lib/{types.js → cjs/types.js} +0 -0
- package/lib/{visitor.d.ts → cjs/visitor.d.ts} +1 -1
- package/lib/{visitor.js → cjs/visitor.js} +17 -17
- package/lib/esm/binder.d.ts +2 -0
- package/lib/esm/binder.js +296 -0
- package/lib/esm/checker.d.ts +14 -0
- package/lib/esm/checker.js +169 -0
- package/lib/esm/core.d.ts +1 -0
- package/lib/esm/core.js +10 -0
- package/lib/esm/error.d.ts +3 -0
- package/lib/esm/error.js +10 -0
- package/lib/esm/index.d.ts +5 -0
- package/lib/esm/index.js +6 -0
- package/lib/esm/parser.d.ts +84 -0
- package/lib/esm/parser.js +700 -0
- package/lib/esm/scanner.d.ts +52 -0
- package/lib/esm/scanner.js +581 -0
- package/lib/esm/service/codeAction.d.ts +12 -0
- package/lib/esm/service/codeAction.js +208 -0
- package/lib/esm/service/colorProvider.d.ts +6 -0
- package/lib/esm/service/colorProvider.js +69 -0
- package/lib/esm/service/command/ChangeAllOtherEdgeOpsAndFixGraphCommand.d.ts +10 -0
- package/lib/esm/service/command/ChangeAllOtherEdgeOpsAndFixGraphCommand.js +38 -0
- package/lib/esm/service/command/ChangeEdgeOpCommand.d.ts +10 -0
- package/lib/esm/service/command/ChangeEdgeOpCommand.js +32 -0
- package/lib/esm/service/command/ConsolidateDescendantsCommand.d.ts +10 -0
- package/lib/esm/service/command/ConsolidateDescendantsCommand.js +83 -0
- package/lib/esm/service/command/RemoveSemicolons.d.ts +10 -0
- package/lib/esm/service/command/RemoveSemicolons.js +37 -0
- package/lib/esm/service/command/common.d.ts +31 -0
- package/lib/esm/service/command/common.js +22 -0
- package/lib/esm/service/completion.d.ts +4 -0
- package/lib/esm/service/completion.js +137 -0
- package/lib/esm/service/hover.d.ts +4 -0
- package/lib/esm/service/hover.js +119 -0
- package/lib/esm/service/languageFacts.d.ts +683 -0
- package/lib/esm/service/languageFacts.js +997 -0
- package/lib/esm/service/polyfill.d.ts +16 -0
- package/lib/esm/service/polyfill.js +2 -0
- package/lib/esm/service/reference.d.ts +5 -0
- package/lib/esm/service/reference.js +66 -0
- package/lib/esm/service/rename.d.ts +4 -0
- package/lib/esm/service/rename.js +45 -0
- package/lib/esm/service/service.d.ts +28 -0
- package/lib/esm/service/service.js +35 -0
- package/lib/esm/service/util.d.ts +11 -0
- package/lib/esm/service/util.js +44 -0
- package/lib/esm/service/validation.d.ts +4 -0
- package/lib/esm/service/validation.js +20 -0
- package/lib/esm/tester.d.ts +1 -0
- package/lib/esm/tester.js +21 -0
- package/lib/esm/types.d.ts +396 -0
- package/lib/esm/types.js +71 -0
- package/lib/esm/visitor.d.ts +2 -0
- package/lib/esm/visitor.js +74 -0
- package/package.json +13 -10
- package/lib/index.d.ts +0 -5
- package/lib/service/service.js +0 -39
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const vscode_languageserver_textdocument_1 = require("vscode-languageserver-textdocument");
|
|
4
|
+
const parser_js_1 = require("./parser.js");
|
|
5
|
+
const binder_js_1 = require("./binder.js");
|
|
6
|
+
const checker_js_1 = require("./checker.js");
|
|
7
|
+
const completion_js_1 = require("./service/completion.js");
|
|
8
|
+
const text = `graph {
|
|
9
|
+
node_name_a -- node_name_b [color=blue,
|
|
10
|
+
];
|
|
11
|
+
}`;
|
|
12
|
+
function main() {
|
|
13
|
+
const parser = new parser_js_1.Parser();
|
|
14
|
+
const sf = parser.parse(text);
|
|
15
|
+
(0, binder_js_1.bindSourceFile)(sf);
|
|
16
|
+
(0, checker_js_1.checkSourceFile)(sf);
|
|
17
|
+
const doc = vscode_languageserver_textdocument_1.TextDocument.create("inmemory://model.json", "DOT", 0, text);
|
|
18
|
+
const requestOffset = text.indexOf("color=blue,\n\t") + "color=blue,\n\t".length;
|
|
19
|
+
const completions = (0, completion_js_1.getCompletions)(doc, sf, doc.positionAt(requestOffset));
|
|
20
|
+
console.dir(completions);
|
|
21
|
+
}
|
|
22
|
+
main();
|
|
23
|
+
//# sourceMappingURL=tester.js.map
|
|
File without changes
|
|
File without changes
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { SyntaxNode, SyntaxNodeArray } from "./types";
|
|
1
|
+
import { SyntaxNode, SyntaxNodeArray } from "./types.js";
|
|
2
2
|
export declare function forEachChild<TReturn>(node: SyntaxNode, cbNode: (node: SyntaxNode) => TReturn, cbNodes?: (nodes: SyntaxNodeArray<SyntaxNode>) => TReturn): TReturn | undefined;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.forEachChild = void 0;
|
|
4
|
-
const
|
|
4
|
+
const types_js_1 = require("./types.js");
|
|
5
5
|
function visitNode(cbNode, node) {
|
|
6
6
|
return node && cbNode(node);
|
|
7
7
|
}
|
|
@@ -18,56 +18,56 @@ function visitNodes(cbNode, cbNodes, nodes) {
|
|
|
18
18
|
return undefined;
|
|
19
19
|
}
|
|
20
20
|
function forEachChild(node, cbNode, cbNodes) {
|
|
21
|
-
if (!node || node.kind <=
|
|
21
|
+
if (!node || node.kind <= types_js_1.SyntaxKind.LastKeyword)
|
|
22
22
|
return;
|
|
23
23
|
switch (node.kind) {
|
|
24
|
-
case
|
|
25
|
-
case
|
|
24
|
+
case types_js_1.SyntaxKind.DirectedGraph:
|
|
25
|
+
case types_js_1.SyntaxKind.UndirectedGraph:
|
|
26
26
|
return visitNodes(cbNode, cbNodes, node.statements)
|
|
27
27
|
|| visitNode(cbNode, node.strict)
|
|
28
28
|
|| visitNode(cbNode, node.id);
|
|
29
|
-
case
|
|
29
|
+
case types_js_1.SyntaxKind.AttributeStatement:
|
|
30
30
|
return visitNodes(cbNode, cbNodes, node.attributes)
|
|
31
31
|
|| visitNode(cbNode, node.subject)
|
|
32
32
|
|| visitNode(cbNode, node.terminator);
|
|
33
|
-
case
|
|
33
|
+
case types_js_1.SyntaxKind.EdgeStatement:
|
|
34
34
|
return visitNodes(cbNode, cbNodes, node.attributes)
|
|
35
35
|
|| visitNodes(cbNode, cbNodes, node.rhs)
|
|
36
36
|
|| visitNode(cbNode, node.source)
|
|
37
37
|
|| visitNode(cbNode, node.terminator);
|
|
38
|
-
case
|
|
38
|
+
case types_js_1.SyntaxKind.NodeStatement:
|
|
39
39
|
return visitNodes(cbNode, cbNodes, node.attributes)
|
|
40
40
|
|| visitNode(cbNode, node.id)
|
|
41
41
|
|| visitNode(cbNode, node.terminator);
|
|
42
|
-
case
|
|
42
|
+
case types_js_1.SyntaxKind.SubGraph:
|
|
43
43
|
return visitNodes(cbNode, cbNodes, node.statements)
|
|
44
44
|
|| visitNode(cbNode, node.id);
|
|
45
|
-
case
|
|
45
|
+
case types_js_1.SyntaxKind.SubGraphStatement:
|
|
46
46
|
return visitNode(cbNode, node.subgraph)
|
|
47
47
|
|| visitNode(cbNode, node.terminator);
|
|
48
|
-
case
|
|
48
|
+
case types_js_1.SyntaxKind.IdEqualsIdStatement:
|
|
49
49
|
return visitNode(cbNode, node.leftId)
|
|
50
50
|
|| visitNode(cbNode, node.rightId)
|
|
51
51
|
|| visitNode(cbNode, node.terminator);
|
|
52
|
-
case
|
|
52
|
+
case types_js_1.SyntaxKind.QuotedTextIdentifier:
|
|
53
53
|
return visitNodes(cbNode, cbNodes, node.values);
|
|
54
|
-
case
|
|
54
|
+
case types_js_1.SyntaxKind.EdgeRhs:
|
|
55
55
|
return visitNode(cbNode, node.operation)
|
|
56
56
|
|| visitNode(cbNode, node.target);
|
|
57
|
-
case
|
|
57
|
+
case types_js_1.SyntaxKind.AttributeContainer:
|
|
58
58
|
return visitNodes(cbNode, cbNodes, node.assignments);
|
|
59
|
-
case
|
|
59
|
+
case types_js_1.SyntaxKind.Assignment:
|
|
60
60
|
return visitNode(cbNode, node.leftId)
|
|
61
61
|
|| visitNode(cbNode, node.rightId)
|
|
62
62
|
|| visitNode(cbNode, node.terminator);
|
|
63
|
-
case
|
|
63
|
+
case types_js_1.SyntaxKind.NormalPortDeclaration:
|
|
64
64
|
return visitNode(cbNode, node.colon)
|
|
65
65
|
|| visitNode(cbNode, node.id)
|
|
66
66
|
|| visitNode(cbNode, node.compassPt);
|
|
67
|
-
case
|
|
67
|
+
case types_js_1.SyntaxKind.CompassPortDeclaration:
|
|
68
68
|
return visitNode(cbNode, node.colon)
|
|
69
69
|
|| visitNode(cbNode, node.compassPt);
|
|
70
|
-
case
|
|
70
|
+
case types_js_1.SyntaxKind.NodeId:
|
|
71
71
|
return visitNode(cbNode, node.port)
|
|
72
72
|
|| visitNode(cbNode, node.id);
|
|
73
73
|
default:
|
|
@@ -0,0 +1,296 @@
|
|
|
1
|
+
import { SyntaxKind, } from "./types.js";
|
|
2
|
+
import { getIdentifierText, nodeContainsErrors } from "./checker.js";
|
|
3
|
+
import { isIdentifierNode } from "./parser.js";
|
|
4
|
+
const binder = createBinder();
|
|
5
|
+
export function bindSourceFile(file) {
|
|
6
|
+
binder.bind(file);
|
|
7
|
+
}
|
|
8
|
+
function createBinder() {
|
|
9
|
+
let parent = undefined;
|
|
10
|
+
let symbolTable = undefined;
|
|
11
|
+
let colorTable = undefined;
|
|
12
|
+
let graphContext = 0;
|
|
13
|
+
function bind(node) {
|
|
14
|
+
if (!node)
|
|
15
|
+
return;
|
|
16
|
+
const saveParent = parent;
|
|
17
|
+
const saveContext = graphContext;
|
|
18
|
+
node.parent = saveParent;
|
|
19
|
+
node.graphContext = saveContext;
|
|
20
|
+
parent = node;
|
|
21
|
+
innerBind(node);
|
|
22
|
+
parent = saveParent;
|
|
23
|
+
graphContext = saveContext;
|
|
24
|
+
}
|
|
25
|
+
function innerBind(node) {
|
|
26
|
+
switch (node.kind) {
|
|
27
|
+
case SyntaxKind.DirectedGraph:
|
|
28
|
+
case SyntaxKind.UndirectedGraph:
|
|
29
|
+
return bindGraph(node);
|
|
30
|
+
case SyntaxKind.AttributeStatement:
|
|
31
|
+
return bindAttributeStatement(node);
|
|
32
|
+
case SyntaxKind.EdgeStatement:
|
|
33
|
+
return bindEdgeStatement(node);
|
|
34
|
+
case SyntaxKind.NodeStatement:
|
|
35
|
+
return bindNodeStatement(node);
|
|
36
|
+
case SyntaxKind.SubGraph:
|
|
37
|
+
return bindSubGraph(node);
|
|
38
|
+
case SyntaxKind.SubGraphStatement:
|
|
39
|
+
return bindSubGraphStatement(node);
|
|
40
|
+
case SyntaxKind.IdEqualsIdStatement:
|
|
41
|
+
return bindIdEqualsIdStatement(node);
|
|
42
|
+
case SyntaxKind.QuotedTextIdentifier:
|
|
43
|
+
return bindQuotedTextIdentifier(node);
|
|
44
|
+
case SyntaxKind.EdgeRhs:
|
|
45
|
+
return bindEdgeRhs(node);
|
|
46
|
+
case SyntaxKind.AttributeContainer:
|
|
47
|
+
return bindAttributeContainer(node);
|
|
48
|
+
case SyntaxKind.Assignment:
|
|
49
|
+
return bindAssignment(node);
|
|
50
|
+
case SyntaxKind.NormalPortDeclaration:
|
|
51
|
+
return bindNormalPortDeclaration(node);
|
|
52
|
+
case SyntaxKind.CompassPortDeclaration:
|
|
53
|
+
return bindCompassPortDeclaration(node);
|
|
54
|
+
case SyntaxKind.NodeId:
|
|
55
|
+
return bindNodeId(node);
|
|
56
|
+
default:
|
|
57
|
+
if (node.kind >= SyntaxKind.FirstNode)
|
|
58
|
+
throw "TODO";
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
function bindGraph(node) {
|
|
62
|
+
if (node.strict) {
|
|
63
|
+
graphContext |= 2;
|
|
64
|
+
}
|
|
65
|
+
switch (node.kind) {
|
|
66
|
+
case SyntaxKind.DirectedGraph:
|
|
67
|
+
graphContext |= 4;
|
|
68
|
+
break;
|
|
69
|
+
case SyntaxKind.UndirectedGraph:
|
|
70
|
+
graphContext |= 8;
|
|
71
|
+
break;
|
|
72
|
+
}
|
|
73
|
+
if (node.id) {
|
|
74
|
+
ensureGlobalSymbol(node.id);
|
|
75
|
+
bind(node.id);
|
|
76
|
+
}
|
|
77
|
+
;
|
|
78
|
+
if (node.strict)
|
|
79
|
+
bind(node.strict);
|
|
80
|
+
bindChildren(node.statements);
|
|
81
|
+
}
|
|
82
|
+
function bindAttributeStatement(node) {
|
|
83
|
+
bind(node.subject);
|
|
84
|
+
bindChildren(node.attributes);
|
|
85
|
+
if (node.terminator)
|
|
86
|
+
bind(node.terminator);
|
|
87
|
+
}
|
|
88
|
+
function bindEdgeStatement(node) {
|
|
89
|
+
bindChildren(node.attributes);
|
|
90
|
+
bindChildren(node.rhs);
|
|
91
|
+
bind(node.source);
|
|
92
|
+
if (node.terminator)
|
|
93
|
+
bind(node.terminator);
|
|
94
|
+
}
|
|
95
|
+
function bindNodeStatement(node) {
|
|
96
|
+
bind(node.id);
|
|
97
|
+
bindChildren(node.attributes);
|
|
98
|
+
if (node.terminator)
|
|
99
|
+
bind(node.terminator);
|
|
100
|
+
}
|
|
101
|
+
function bindSubGraph(node) {
|
|
102
|
+
if (node.id) {
|
|
103
|
+
bind(node.id);
|
|
104
|
+
}
|
|
105
|
+
;
|
|
106
|
+
bindChildren(node.statements);
|
|
107
|
+
}
|
|
108
|
+
function bindSubGraphStatement(node) {
|
|
109
|
+
bind(node.subgraph);
|
|
110
|
+
if (node.terminator)
|
|
111
|
+
bind(node.terminator);
|
|
112
|
+
}
|
|
113
|
+
function bindIdEqualsIdStatement(node) {
|
|
114
|
+
bind(node.leftId);
|
|
115
|
+
bind(node.rightId);
|
|
116
|
+
if (node.rightId && !nodeContainsErrors(node.rightId)) {
|
|
117
|
+
if (isAttributeName("color", node.leftId)) {
|
|
118
|
+
ensureGlobalColor(node.rightId);
|
|
119
|
+
}
|
|
120
|
+
else if (isAttributeName("fillcolor", node.leftId)) {
|
|
121
|
+
ensureGlobalColor(node.rightId);
|
|
122
|
+
}
|
|
123
|
+
else if (isAttributeName("bgcolor", node.leftId)) {
|
|
124
|
+
ensureGlobalColor(node.rightId);
|
|
125
|
+
}
|
|
126
|
+
else if (isAttributeName("fontcolor", node.leftId)) {
|
|
127
|
+
ensureGlobalColor(node.rightId);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
if (node.terminator)
|
|
131
|
+
bind(node.terminator);
|
|
132
|
+
}
|
|
133
|
+
function bindQuotedTextIdentifier(node) {
|
|
134
|
+
bindChildren(node.values);
|
|
135
|
+
node.concatenation = node.values.map(v => v.text).join("");
|
|
136
|
+
}
|
|
137
|
+
function bindEdgeRhs(node) {
|
|
138
|
+
bind(node.operation);
|
|
139
|
+
bind(node.target);
|
|
140
|
+
}
|
|
141
|
+
function bindAttributeContainer(node) {
|
|
142
|
+
bind(node.openBracket);
|
|
143
|
+
bindChildren(node.assignments);
|
|
144
|
+
bind(node.closeBracket);
|
|
145
|
+
}
|
|
146
|
+
function bindAssignment(node) {
|
|
147
|
+
const attrContainer = node.parent;
|
|
148
|
+
console.assert(!!attrContainer);
|
|
149
|
+
const superParentStatement = attrContainer.parent;
|
|
150
|
+
console.assert(!!superParentStatement);
|
|
151
|
+
bind(node.leftId);
|
|
152
|
+
let carrierIdentifier = undefined;
|
|
153
|
+
switch (superParentStatement.kind) {
|
|
154
|
+
case SyntaxKind.NodeStatement:
|
|
155
|
+
carrierIdentifier = superParentStatement.id.id;
|
|
156
|
+
break;
|
|
157
|
+
case SyntaxKind.EdgeStatement:
|
|
158
|
+
break;
|
|
159
|
+
case SyntaxKind.SubGraphStatement:
|
|
160
|
+
break;
|
|
161
|
+
case SyntaxKind.AttributeStatement:
|
|
162
|
+
break;
|
|
163
|
+
}
|
|
164
|
+
if (carrierIdentifier)
|
|
165
|
+
ensureMemberSymbol(node.leftId, carrierIdentifier);
|
|
166
|
+
bind(node.rightId);
|
|
167
|
+
if (node.rightId && !nodeContainsErrors(node.rightId)) {
|
|
168
|
+
if (isAttributeName("color", node.leftId)) {
|
|
169
|
+
ensureGlobalColor(node.rightId);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
if (node.terminator)
|
|
173
|
+
bind(node.terminator);
|
|
174
|
+
}
|
|
175
|
+
function bindNormalPortDeclaration(node) {
|
|
176
|
+
bind(node.colon);
|
|
177
|
+
ensureGlobalSymbol(node.id);
|
|
178
|
+
bind(node.id);
|
|
179
|
+
if (node.compassPt)
|
|
180
|
+
bind(node.compassPt);
|
|
181
|
+
}
|
|
182
|
+
function bindCompassPortDeclaration(node) {
|
|
183
|
+
bind(node.colon);
|
|
184
|
+
if (node.compassPt)
|
|
185
|
+
bind(node.compassPt);
|
|
186
|
+
}
|
|
187
|
+
function bindNodeId(node) {
|
|
188
|
+
ensureGlobalSymbol(node.id);
|
|
189
|
+
bind(node.id);
|
|
190
|
+
if (node.port)
|
|
191
|
+
bind(node.port);
|
|
192
|
+
}
|
|
193
|
+
function bindChildren(nodes) {
|
|
194
|
+
for (const n of nodes)
|
|
195
|
+
bind(n);
|
|
196
|
+
}
|
|
197
|
+
function createSymbolTable() {
|
|
198
|
+
return new Map();
|
|
199
|
+
}
|
|
200
|
+
function createColorTable() {
|
|
201
|
+
return new Map();
|
|
202
|
+
}
|
|
203
|
+
function ensureMemberSymbol(node, carrier) {
|
|
204
|
+
if (node && carrier && isIdentifierNode(node)) {
|
|
205
|
+
const name = getIdentifierText(node);
|
|
206
|
+
if (name === undefined)
|
|
207
|
+
return;
|
|
208
|
+
const carrierSymbol = carrier.symbol;
|
|
209
|
+
if (carrierSymbol === undefined)
|
|
210
|
+
throw "carrierSymbol is undefined";
|
|
211
|
+
let symbols = carrierSymbol.members;
|
|
212
|
+
if (symbols === undefined)
|
|
213
|
+
carrierSymbol.members = symbols = createSymbolTable();
|
|
214
|
+
ensureSymbolOnTable(name, node, symbols);
|
|
215
|
+
return;
|
|
216
|
+
}
|
|
217
|
+
console.warn("ensureSymbol called on non-identifier node");
|
|
218
|
+
debugger;
|
|
219
|
+
}
|
|
220
|
+
function ensureGlobalSymbol(node) {
|
|
221
|
+
if (node && isIdentifierNode(node)) {
|
|
222
|
+
const symbols = symbolTable;
|
|
223
|
+
const name = getIdentifierText(node);
|
|
224
|
+
if (name === undefined)
|
|
225
|
+
return;
|
|
226
|
+
if (symbols === undefined)
|
|
227
|
+
throw "symbolTable is undefined";
|
|
228
|
+
ensureSymbolOnTable(name, node, symbols);
|
|
229
|
+
return;
|
|
230
|
+
}
|
|
231
|
+
console.warn("ensureSymbol called on non-identifier node");
|
|
232
|
+
debugger;
|
|
233
|
+
}
|
|
234
|
+
function ensureSymbolOnTable(name, node, symbols) {
|
|
235
|
+
if (!name)
|
|
236
|
+
return;
|
|
237
|
+
let sym = symbols.get(name);
|
|
238
|
+
if (sym === undefined) {
|
|
239
|
+
sym = createSymbol(name, node);
|
|
240
|
+
symbols.set(name, sym);
|
|
241
|
+
}
|
|
242
|
+
else {
|
|
243
|
+
if (!sym.references)
|
|
244
|
+
sym.references = [node];
|
|
245
|
+
else
|
|
246
|
+
sym.references.push(node);
|
|
247
|
+
}
|
|
248
|
+
node.symbol = sym;
|
|
249
|
+
}
|
|
250
|
+
function ensureGlobalColor(node) {
|
|
251
|
+
if (node && isIdentifierNode(node)) {
|
|
252
|
+
const colors = colorTable;
|
|
253
|
+
const name = getIdentifierText(node);
|
|
254
|
+
if (name === undefined)
|
|
255
|
+
return;
|
|
256
|
+
if (colors === undefined)
|
|
257
|
+
throw "symbolTable is undefined";
|
|
258
|
+
const color = createColor(node);
|
|
259
|
+
colors.set(name, color);
|
|
260
|
+
return;
|
|
261
|
+
}
|
|
262
|
+
console.warn("ensureSymbol called on non-identifier node");
|
|
263
|
+
debugger;
|
|
264
|
+
}
|
|
265
|
+
function createSymbol(name, node) {
|
|
266
|
+
if (!name)
|
|
267
|
+
throw "name is falsy";
|
|
268
|
+
if (!node)
|
|
269
|
+
throw "node is undefined or null";
|
|
270
|
+
return {
|
|
271
|
+
name,
|
|
272
|
+
firstMention: node,
|
|
273
|
+
references: undefined,
|
|
274
|
+
};
|
|
275
|
+
}
|
|
276
|
+
function createColor(node) {
|
|
277
|
+
return {
|
|
278
|
+
node,
|
|
279
|
+
};
|
|
280
|
+
}
|
|
281
|
+
function isAttributeName(name, id) {
|
|
282
|
+
return id ? getIdentifierText(id).trim().toLowerCase() === name : false;
|
|
283
|
+
}
|
|
284
|
+
return {
|
|
285
|
+
bind: file => {
|
|
286
|
+
symbolTable = createSymbolTable();
|
|
287
|
+
colorTable = createColorTable();
|
|
288
|
+
const { graph } = file;
|
|
289
|
+
if (graph)
|
|
290
|
+
bind(graph);
|
|
291
|
+
file.symbols = symbolTable;
|
|
292
|
+
file.colors = colorTable;
|
|
293
|
+
},
|
|
294
|
+
};
|
|
295
|
+
}
|
|
296
|
+
//# sourceMappingURL=binder.js.map
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { SyntaxNode, Identifier, SyntaxKind, Graph, EdgeStatement, EdgeRhs, SourceFile, SubGraphStatement, NodeId, AttributeStatement, Statement, StatementOf, Token } from "./types.js";
|
|
2
|
+
export declare function checkSourceFile(file: SourceFile): void;
|
|
3
|
+
export declare function findNodeAtOffset(root: SyntaxNode, offset: number, inclusiveEnd?: boolean): SyntaxNode | undefined;
|
|
4
|
+
export declare function getAllowedEdgeOperation(graph: Graph): SyntaxKind.DirectedEdgeOp | SyntaxKind.UndirectedEdgeOp;
|
|
5
|
+
export declare function findAllEdges(node: SyntaxNode): EdgeRhs[];
|
|
6
|
+
export declare function findOptionalSemicolons(node: SyntaxNode): Token<SyntaxKind.SemicolonToken>[];
|
|
7
|
+
export declare function findAllStatements<T extends Statement["kind"]>(node: SyntaxNode, kind?: T): StatementOf<T>[];
|
|
8
|
+
export declare function isAttrStatement(node: SyntaxNode): node is AttributeStatement;
|
|
9
|
+
export declare function isEdgeStatement(node: SyntaxNode): node is EdgeStatement;
|
|
10
|
+
export declare function isSubGraphStatement(node: SyntaxNode): node is SubGraphStatement;
|
|
11
|
+
export declare function isNodeId(node: SyntaxNode): node is NodeId;
|
|
12
|
+
export declare function edgeStatementHasAttributes(es: EdgeStatement): boolean;
|
|
13
|
+
export declare function getIdentifierText(n: Identifier): string;
|
|
14
|
+
export declare function nodeContainsErrors(node: SyntaxNode): boolean;
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
import { SyntaxKind, DiagnosticCategory, } from "./types.js";
|
|
2
|
+
import { assertNever, getStart } from "./service/util.js";
|
|
3
|
+
import { forEachChild } from "./visitor.js";
|
|
4
|
+
export function checkSourceFile(file) {
|
|
5
|
+
const g = file.graph;
|
|
6
|
+
if (g) {
|
|
7
|
+
const messages = checkGraphSemantics(file, g);
|
|
8
|
+
if (messages) {
|
|
9
|
+
file.diagnostics.push.apply(file.diagnostics, messages);
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
function getNarrowerNode(offset, prev, toCheck) {
|
|
14
|
+
const prevRange = prev.end - prev.pos;
|
|
15
|
+
if (toCheck.pos <= offset && offset <= toCheck.end) {
|
|
16
|
+
let nrange = toCheck.end - toCheck.pos;
|
|
17
|
+
if (nrange < prevRange) {
|
|
18
|
+
return toCheck;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
return prev;
|
|
22
|
+
}
|
|
23
|
+
function rangeContainsOffset(range, offset, inclusiveEnd) {
|
|
24
|
+
return inclusiveEnd
|
|
25
|
+
? range.pos <= offset && offset <= range.end
|
|
26
|
+
: range.pos <= offset && offset < range.end;
|
|
27
|
+
}
|
|
28
|
+
export function findNodeAtOffset(root, offset, inclusiveEnd = false) {
|
|
29
|
+
if (root.pos === offset && root.pos === root.end)
|
|
30
|
+
return root;
|
|
31
|
+
if (rangeContainsOffset(root, offset, inclusiveEnd)) {
|
|
32
|
+
const narrowerChild = forEachChild(root, child => findNodeAtOffset(child, offset, inclusiveEnd));
|
|
33
|
+
return narrowerChild ? narrowerChild : root;
|
|
34
|
+
}
|
|
35
|
+
return undefined;
|
|
36
|
+
}
|
|
37
|
+
export function getAllowedEdgeOperation(graph) {
|
|
38
|
+
return graph.kind === SyntaxKind.DirectedGraph
|
|
39
|
+
? SyntaxKind.DirectedEdgeOp
|
|
40
|
+
: SyntaxKind.UndirectedEdgeOp;
|
|
41
|
+
}
|
|
42
|
+
function checkGraphSemantics(file, root) {
|
|
43
|
+
const expectedEdgeOp = getAllowedEdgeOperation(root);
|
|
44
|
+
const invalidEdgeRhses = findEdgeErrors(expectedEdgeOp, root);
|
|
45
|
+
return invalidEdgeRhses == undefined || invalidEdgeRhses.length === 0
|
|
46
|
+
? undefined
|
|
47
|
+
: createEdgeViolationDiagnostics(file, expectedEdgeOp, invalidEdgeRhses);
|
|
48
|
+
}
|
|
49
|
+
export function findAllEdges(node) {
|
|
50
|
+
const allEdges = [];
|
|
51
|
+
forEachChild(node, child => {
|
|
52
|
+
if (isEdgeStatement(child)) {
|
|
53
|
+
if (child.rhs && child.rhs.length > 0) {
|
|
54
|
+
for (const edgeRhs of child.rhs)
|
|
55
|
+
allEdges.push(edgeRhs);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
const childEdges = findAllEdges(child);
|
|
59
|
+
if (childEdges && childEdges.length > 0)
|
|
60
|
+
allEdges.push.apply(allEdges, childEdges);
|
|
61
|
+
});
|
|
62
|
+
return allEdges;
|
|
63
|
+
}
|
|
64
|
+
export function findOptionalSemicolons(node) {
|
|
65
|
+
const statements = findAllStatements(node);
|
|
66
|
+
const terminators = statements.map(p => p.terminator);
|
|
67
|
+
return terminators.filter(t => !!t);
|
|
68
|
+
}
|
|
69
|
+
function isStatement(node) {
|
|
70
|
+
return node.kind === SyntaxKind.SubGraphStatement
|
|
71
|
+
|| node.kind === SyntaxKind.EdgeStatement
|
|
72
|
+
|| node.kind === SyntaxKind.NodeStatement
|
|
73
|
+
|| node.kind === SyntaxKind.IdEqualsIdStatement
|
|
74
|
+
|| node.kind === SyntaxKind.AttributeStatement;
|
|
75
|
+
}
|
|
76
|
+
export function findAllStatements(node, kind) {
|
|
77
|
+
const allStatements = [];
|
|
78
|
+
forEachChild(node, child => {
|
|
79
|
+
if ((kind === undefined && isStatement(child)) || (child.kind === kind)) {
|
|
80
|
+
allStatements.push(child);
|
|
81
|
+
}
|
|
82
|
+
const childStatements = findAllStatements(child, kind);
|
|
83
|
+
if (childStatements && childStatements.length > 0)
|
|
84
|
+
allStatements.push.apply(allStatements, childStatements);
|
|
85
|
+
});
|
|
86
|
+
return allStatements;
|
|
87
|
+
}
|
|
88
|
+
function findEdgeErrors(expectedEdgeOp, node) {
|
|
89
|
+
const edges = findAllEdges(node);
|
|
90
|
+
const wrongEdges = edges && edges.length > 0
|
|
91
|
+
? edges.filter(e => e.operation.kind !== expectedEdgeOp)
|
|
92
|
+
: undefined;
|
|
93
|
+
if (wrongEdges && wrongEdges.length > 0) {
|
|
94
|
+
wrongEdges.forEach(e => e.operation.flags |= 2);
|
|
95
|
+
return wrongEdges;
|
|
96
|
+
}
|
|
97
|
+
return undefined;
|
|
98
|
+
}
|
|
99
|
+
function createEdgeViolationDiagnostics(file, expectedEdgeOp, violators) {
|
|
100
|
+
const op = expectedEdgeOp === SyntaxKind.UndirectedEdgeOp ? "--" : "->";
|
|
101
|
+
const graphType = expectedEdgeOp === SyntaxKind.UndirectedEdgeOp ? "undirected" : "directed";
|
|
102
|
+
const message = `Invalid edge operation, use "${op}" in ${graphType} graph`;
|
|
103
|
+
const code = createCheckerError(0);
|
|
104
|
+
const category = DiagnosticCategory.Error;
|
|
105
|
+
violators.forEach(edge => edge.operation.flags |= 2);
|
|
106
|
+
return violators.map(edge => {
|
|
107
|
+
const start = getStart(file, edge.operation);
|
|
108
|
+
const end = edge.operation.end;
|
|
109
|
+
return {
|
|
110
|
+
message,
|
|
111
|
+
code,
|
|
112
|
+
category,
|
|
113
|
+
start,
|
|
114
|
+
end,
|
|
115
|
+
};
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
function getInvalidEdgeRhs(allowedOp, edges) {
|
|
119
|
+
const res = [];
|
|
120
|
+
for (const e of edges) {
|
|
121
|
+
if (e.operation.kind !== allowedOp)
|
|
122
|
+
res.push(e);
|
|
123
|
+
}
|
|
124
|
+
return res;
|
|
125
|
+
}
|
|
126
|
+
export function isAttrStatement(node) {
|
|
127
|
+
return node.kind === SyntaxKind.AttributeStatement;
|
|
128
|
+
}
|
|
129
|
+
export function isEdgeStatement(node) {
|
|
130
|
+
return node.kind === SyntaxKind.EdgeStatement;
|
|
131
|
+
}
|
|
132
|
+
export function isSubGraphStatement(node) {
|
|
133
|
+
return node.kind === SyntaxKind.SubGraphStatement;
|
|
134
|
+
}
|
|
135
|
+
function isGraph(node) {
|
|
136
|
+
return node.kind === SyntaxKind.DirectedGraph || node.kind === SyntaxKind.UndirectedGraph;
|
|
137
|
+
}
|
|
138
|
+
export function isNodeId(node) {
|
|
139
|
+
return node.kind === SyntaxKind.NodeId;
|
|
140
|
+
}
|
|
141
|
+
export function edgeStatementHasAttributes(es) {
|
|
142
|
+
return es.attributes
|
|
143
|
+
&& es.attributes.length > 0
|
|
144
|
+
&& es.attributes.some(a => a.assignments && a.assignments.length > 0);
|
|
145
|
+
}
|
|
146
|
+
export function getIdentifierText(n) {
|
|
147
|
+
switch (n.kind) {
|
|
148
|
+
case SyntaxKind.HtmlIdentifier:
|
|
149
|
+
return n.htmlContent;
|
|
150
|
+
case SyntaxKind.TextIdentifier:
|
|
151
|
+
return n.text;
|
|
152
|
+
case SyntaxKind.NumericIdentifier:
|
|
153
|
+
return n.text;
|
|
154
|
+
case SyntaxKind.QuotedTextIdentifier:
|
|
155
|
+
return n.concatenation;
|
|
156
|
+
default:
|
|
157
|
+
return assertNever(n);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
function createCheckerError(sub) {
|
|
161
|
+
return {
|
|
162
|
+
source: 4,
|
|
163
|
+
sub,
|
|
164
|
+
};
|
|
165
|
+
}
|
|
166
|
+
export function nodeContainsErrors(node) {
|
|
167
|
+
return (node.flags & 2) === 2;
|
|
168
|
+
}
|
|
169
|
+
//# sourceMappingURL=checker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function createMapFromTemplate<T>(template: Record<string, T>): Map<string, T>;
|
package/lib/esm/core.js
ADDED
package/lib/esm/error.js
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export const diagnosicSource = "DOT";
|
|
2
|
+
const errorCodeLength = 4;
|
|
3
|
+
const subErrorCodeLength = errorCodeLength - 1;
|
|
4
|
+
export function formatError(error) {
|
|
5
|
+
const subCode = (error.sub | 0)
|
|
6
|
+
.toString()
|
|
7
|
+
.padStart(subErrorCodeLength, "0");
|
|
8
|
+
return diagnosicSource + error.source + subCode;
|
|
9
|
+
}
|
|
10
|
+
//# sourceMappingURL=error.js.map
|