umple-lsp-server 0.2.2 → 0.2.4
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/out/formatRules.d.ts +27 -0
- package/out/formatRules.js +114 -0
- package/out/formatRules.js.map +1 -0
- package/out/formatter.d.ts +38 -16
- package/out/formatter.js +336 -52
- package/out/formatter.js.map +1 -1
- package/out/server.js +232 -21
- package/out/server.js.map +1 -1
- package/out/symbolIndex.d.ts +14 -0
- package/out/symbolIndex.js +35 -0
- package/out/symbolIndex.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Formatting rule definitions for the syntax-aware formatter.
|
|
3
|
+
*
|
|
4
|
+
* Node-type classification for indentation and skip regions.
|
|
5
|
+
* All node names are verified against the actual tree-sitter grammar.
|
|
6
|
+
*/
|
|
7
|
+
declare const TreeSitter: any;
|
|
8
|
+
type Tree = InstanceType<typeof TreeSitter.Tree>;
|
|
9
|
+
/** Node types whose body content gets +1 indent level. */
|
|
10
|
+
export declare const INDENT_NODES: Set<string>;
|
|
11
|
+
/** Top-level declaration node types that should be separated by blank lines. */
|
|
12
|
+
export declare const TOP_LEVEL_DECL_NODES: Set<string>;
|
|
13
|
+
/** Node types whose content is verbatim (embedded code — do not reindent). */
|
|
14
|
+
export declare const SKIP_NODES: Set<string>;
|
|
15
|
+
/**
|
|
16
|
+
* Check if a line falls strictly inside a verbatim/skip node.
|
|
17
|
+
* Boundary lines (the line with opening `{` and closing `}`) are NOT skipped —
|
|
18
|
+
* they're Umple-structural and should be formatted normally.
|
|
19
|
+
*/
|
|
20
|
+
export declare function isVerbatimLine(tree: Tree, line: number): boolean;
|
|
21
|
+
/**
|
|
22
|
+
* Compute the structural indent depth for a line from its AST ancestors.
|
|
23
|
+
* Only counts indent-contributing ancestors whose body starts ABOVE this line
|
|
24
|
+
* (so the opening line of `class A {` doesn't get +1 from its own node).
|
|
25
|
+
*/
|
|
26
|
+
export declare function computeStructuralDepth(tree: Tree, line: number, column: number): number;
|
|
27
|
+
export {};
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Formatting rule definitions for the syntax-aware formatter.
|
|
4
|
+
*
|
|
5
|
+
* Node-type classification for indentation and skip regions.
|
|
6
|
+
* All node names are verified against the actual tree-sitter grammar.
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.SKIP_NODES = exports.TOP_LEVEL_DECL_NODES = exports.INDENT_NODES = void 0;
|
|
10
|
+
exports.isVerbatimLine = isVerbatimLine;
|
|
11
|
+
exports.computeStructuralDepth = computeStructuralDepth;
|
|
12
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
13
|
+
const TreeSitter = require("web-tree-sitter");
|
|
14
|
+
/** Node types whose body content gets +1 indent level. */
|
|
15
|
+
exports.INDENT_NODES = new Set([
|
|
16
|
+
"class_definition",
|
|
17
|
+
"interface_definition",
|
|
18
|
+
"trait_definition",
|
|
19
|
+
"association_class_definition",
|
|
20
|
+
"enum_definition",
|
|
21
|
+
"association_definition",
|
|
22
|
+
"mixset_definition",
|
|
23
|
+
"state_machine",
|
|
24
|
+
"statemachine_definition",
|
|
25
|
+
"state",
|
|
26
|
+
"before_after",
|
|
27
|
+
"toplevel_code_injection",
|
|
28
|
+
"filter_definition",
|
|
29
|
+
"method_declaration",
|
|
30
|
+
]);
|
|
31
|
+
/** Top-level declaration node types that should be separated by blank lines. */
|
|
32
|
+
exports.TOP_LEVEL_DECL_NODES = new Set([
|
|
33
|
+
"class_definition",
|
|
34
|
+
"interface_definition",
|
|
35
|
+
"trait_definition",
|
|
36
|
+
"association_class_definition",
|
|
37
|
+
"enum_definition",
|
|
38
|
+
"association_definition",
|
|
39
|
+
"statemachine_definition",
|
|
40
|
+
"mixset_definition",
|
|
41
|
+
"toplevel_code_injection",
|
|
42
|
+
"namespace_declaration",
|
|
43
|
+
"use_statement",
|
|
44
|
+
"generate_statement",
|
|
45
|
+
"requirement_definition",
|
|
46
|
+
"external_definition",
|
|
47
|
+
]);
|
|
48
|
+
/** Node types whose content is verbatim (embedded code — do not reindent). */
|
|
49
|
+
exports.SKIP_NODES = new Set([
|
|
50
|
+
"code_content",
|
|
51
|
+
"template_body",
|
|
52
|
+
]);
|
|
53
|
+
/**
|
|
54
|
+
* Check if a line falls strictly inside a verbatim/skip node.
|
|
55
|
+
* Boundary lines (the line with opening `{` and closing `}`) are NOT skipped —
|
|
56
|
+
* they're Umple-structural and should be formatted normally.
|
|
57
|
+
*/
|
|
58
|
+
function isVerbatimLine(tree, line) {
|
|
59
|
+
// Walk the tree to find skip nodes that contain this line
|
|
60
|
+
const cursor = tree.rootNode.walk();
|
|
61
|
+
let reachedEnd = false;
|
|
62
|
+
while (!reachedEnd) {
|
|
63
|
+
const node = cursor.currentNode;
|
|
64
|
+
if (exports.SKIP_NODES.has(node.type)) {
|
|
65
|
+
// Strictly between start and end rows (boundary lines are formatted)
|
|
66
|
+
if (node.startPosition.row < line && line < node.endPosition.row) {
|
|
67
|
+
return true;
|
|
68
|
+
}
|
|
69
|
+
// Don't descend into skip nodes
|
|
70
|
+
if (!cursor.gotoNextSibling()) {
|
|
71
|
+
while (!cursor.gotoNextSibling()) {
|
|
72
|
+
if (!cursor.gotoParent()) {
|
|
73
|
+
reachedEnd = true;
|
|
74
|
+
break;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
else if (!cursor.gotoFirstChild()) {
|
|
80
|
+
if (!cursor.gotoNextSibling()) {
|
|
81
|
+
while (!cursor.gotoNextSibling()) {
|
|
82
|
+
if (!cursor.gotoParent()) {
|
|
83
|
+
reachedEnd = true;
|
|
84
|
+
break;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
return false;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Compute the structural indent depth for a line from its AST ancestors.
|
|
94
|
+
* Only counts indent-contributing ancestors whose body starts ABOVE this line
|
|
95
|
+
* (so the opening line of `class A {` doesn't get +1 from its own node).
|
|
96
|
+
*/
|
|
97
|
+
function computeStructuralDepth(tree, line, column) {
|
|
98
|
+
const node = tree.rootNode.descendantForPosition({ row: line, column });
|
|
99
|
+
if (!node)
|
|
100
|
+
return 0;
|
|
101
|
+
let depth = 0;
|
|
102
|
+
let current = node;
|
|
103
|
+
while (current) {
|
|
104
|
+
if (exports.INDENT_NODES.has(current.type)) {
|
|
105
|
+
// Only count if this line is INSIDE the body (not the header line)
|
|
106
|
+
if (current.startPosition.row < line) {
|
|
107
|
+
depth++;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
current = current.parent;
|
|
111
|
+
}
|
|
112
|
+
return depth;
|
|
113
|
+
}
|
|
114
|
+
//# sourceMappingURL=formatRules.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"formatRules.js","sourceRoot":"","sources":["../src/formatRules.ts"],"names":[],"mappings":"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"}
|
package/out/formatter.d.ts
CHANGED
|
@@ -1,31 +1,53 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Syntax-aware document formatter.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
4
|
+
* Uses tree-sitter AST to compute structural indentation instead of
|
|
5
|
+
* naive brace counting. Preserves embedded code regions (code_content,
|
|
6
|
+
* template_body) as verbatim islands.
|
|
6
7
|
*/
|
|
7
8
|
import { TextEdit } from "vscode-languageserver/node";
|
|
9
|
+
declare const TreeSitter: any;
|
|
10
|
+
type Tree = InstanceType<typeof TreeSitter.Tree>;
|
|
8
11
|
/**
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
* @param tree Pre-parsed tree (caller handles tree acquisition)
|
|
12
|
+
* Expand eligible single-line compact state blocks into multi-line format.
|
|
13
|
+
* Returns the modified text (or the original if nothing changed).
|
|
13
14
|
*/
|
|
14
|
-
export declare function
|
|
15
|
-
startLine: number;
|
|
16
|
-
endLine: number;
|
|
17
|
-
}[];
|
|
15
|
+
export declare function expandCompactStates(text: string, tree: Tree): string;
|
|
18
16
|
/**
|
|
19
|
-
* Compute indent edits for an Umple document.
|
|
17
|
+
* Compute indent edits for an Umple document using syntax-aware indentation.
|
|
20
18
|
*
|
|
21
|
-
* @param text
|
|
19
|
+
* @param text Document text
|
|
22
20
|
* @param options Formatting options (tabSize, insertSpaces)
|
|
23
|
-
* @param
|
|
21
|
+
* @param tree Pre-parsed tree-sitter tree
|
|
22
|
+
* @returns Array of TextEdits to apply for correct indentation
|
|
24
23
|
*/
|
|
25
24
|
export declare function computeIndentEdits(text: string, options: {
|
|
26
25
|
tabSize: number;
|
|
27
26
|
insertSpaces: boolean;
|
|
28
|
-
},
|
|
27
|
+
}, tree: Tree): TextEdit[];
|
|
28
|
+
/**
|
|
29
|
+
* Normalize whitespace around `->` in transition and standalone_transition nodes.
|
|
30
|
+
* Only handles single-line nodes. Leaves event, guard, action, and target text verbatim.
|
|
31
|
+
*/
|
|
32
|
+
export declare function fixTransitionSpacing(text: string, tree: Tree): TextEdit[];
|
|
33
|
+
/**
|
|
34
|
+
* Normalize whitespace around the arrow in association_inline and association_member nodes.
|
|
35
|
+
* Only handles single-line nodes. Same child-walking approach as fixTransitionSpacing.
|
|
36
|
+
*/
|
|
37
|
+
export declare function fixAssociationSpacing(text: string, tree: Tree): TextEdit[];
|
|
38
|
+
/**
|
|
39
|
+
* Normalize blank lines between top-level declarations in source_file.
|
|
40
|
+
* Ensures exactly 1 blank line between consecutive top-level named children.
|
|
41
|
+
* Does NOT touch interior body spacing.
|
|
42
|
+
*/
|
|
43
|
+
export declare function normalizeTopLevelBlankLines(text: string, tree: Tree): TextEdit[];
|
|
44
|
+
/**
|
|
45
|
+
* Collect line ranges of code_content and template_body nodes.
|
|
46
|
+
* Kept for backward compatibility with existing callers; the new
|
|
47
|
+
* formatter uses isVerbatimLine() from formatRules instead.
|
|
48
|
+
*/
|
|
49
|
+
export declare function getCodeContentRanges(tree: any): {
|
|
29
50
|
startLine: number;
|
|
30
51
|
endLine: number;
|
|
31
|
-
}[]
|
|
52
|
+
}[];
|
|
53
|
+
export {};
|
package/out/formatter.js
CHANGED
|
@@ -1,19 +1,348 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
/**
|
|
3
|
-
*
|
|
3
|
+
* Syntax-aware document formatter.
|
|
4
4
|
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
5
|
+
* Uses tree-sitter AST to compute structural indentation instead of
|
|
6
|
+
* naive brace counting. Preserves embedded code regions (code_content,
|
|
7
|
+
* template_body) as verbatim islands.
|
|
7
8
|
*/
|
|
8
9
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
-
exports.
|
|
10
|
+
exports.expandCompactStates = expandCompactStates;
|
|
10
11
|
exports.computeIndentEdits = computeIndentEdits;
|
|
12
|
+
exports.fixTransitionSpacing = fixTransitionSpacing;
|
|
13
|
+
exports.fixAssociationSpacing = fixAssociationSpacing;
|
|
14
|
+
exports.normalizeTopLevelBlankLines = normalizeTopLevelBlankLines;
|
|
15
|
+
exports.getCodeContentRanges = getCodeContentRanges;
|
|
11
16
|
const node_1 = require("vscode-languageserver/node");
|
|
17
|
+
const formatRules_1 = require("./formatRules");
|
|
18
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
19
|
+
const TreeSitter = require("web-tree-sitter");
|
|
20
|
+
// ── Phase 0: Compact block expansion ────────────────────────────────────────
|
|
21
|
+
/** Allowed child types inside a state body for expansion eligibility. */
|
|
22
|
+
const EXPANSION_ALLOWED_CHILDREN = new Set([
|
|
23
|
+
"transition", "standalone_transition",
|
|
24
|
+
"{", "}", ";", "identifier",
|
|
25
|
+
]);
|
|
26
|
+
/** Node types that disqualify a state from expansion if found as descendants. */
|
|
27
|
+
const EXPANSION_REJECT_DESCENDANTS = new Set([
|
|
28
|
+
"code_content", "template_body", "action_code", "more_code",
|
|
29
|
+
"line_comment", "block_comment",
|
|
30
|
+
]);
|
|
31
|
+
/**
|
|
32
|
+
* Check if a subtree contains any descendant of the given types.
|
|
33
|
+
*/
|
|
34
|
+
function hasDescendantOfType(node, types) {
|
|
35
|
+
for (let i = 0; i < node.childCount; i++) {
|
|
36
|
+
const child = node.child(i);
|
|
37
|
+
if (types.has(child.type))
|
|
38
|
+
return true;
|
|
39
|
+
if (hasDescendantOfType(child, types))
|
|
40
|
+
return true;
|
|
41
|
+
}
|
|
42
|
+
return false;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Check if a single-line state node is eligible for compact block expansion.
|
|
46
|
+
*/
|
|
47
|
+
function isEligibleForExpansion(stateNode) {
|
|
48
|
+
// Must be single-line
|
|
49
|
+
if (stateNode.startPosition.row !== stateNode.endPosition.row)
|
|
50
|
+
return false;
|
|
51
|
+
// Walk ALL children (including anonymous tokens)
|
|
52
|
+
let hasTransition = false;
|
|
53
|
+
for (let i = 0; i < stateNode.childCount; i++) {
|
|
54
|
+
const child = stateNode.child(i);
|
|
55
|
+
const type = child.type;
|
|
56
|
+
if (EXPANSION_ALLOWED_CHILDREN.has(type)) {
|
|
57
|
+
if (type === "transition" || type === "standalone_transition") {
|
|
58
|
+
hasTransition = true;
|
|
59
|
+
}
|
|
60
|
+
continue;
|
|
61
|
+
}
|
|
62
|
+
// Any other child (||, entry_exit_action, state, method, etc.) → reject
|
|
63
|
+
return false;
|
|
64
|
+
}
|
|
65
|
+
if (!hasTransition)
|
|
66
|
+
return false;
|
|
67
|
+
// Check for embedded-code or comment descendants anywhere in subtree
|
|
68
|
+
if (hasDescendantOfType(stateNode, EXPANSION_REJECT_DESCENDANTS)) {
|
|
69
|
+
return false;
|
|
70
|
+
}
|
|
71
|
+
// Check for ERROR nodes
|
|
72
|
+
if (stateNode.hasError)
|
|
73
|
+
return false;
|
|
74
|
+
return true;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Expand eligible single-line compact state blocks into multi-line format.
|
|
78
|
+
* Returns the modified text (or the original if nothing changed).
|
|
79
|
+
*/
|
|
80
|
+
function expandCompactStates(text, tree) {
|
|
81
|
+
const lines = text.split("\n");
|
|
82
|
+
// Collect eligible state nodes (process in reverse to preserve positions)
|
|
83
|
+
const eligible = [];
|
|
84
|
+
const visit = (node) => {
|
|
85
|
+
if (node.type === "state" && isEligibleForExpansion(node)) {
|
|
86
|
+
eligible.push(node);
|
|
87
|
+
return; // Don't descend — this is single-line
|
|
88
|
+
}
|
|
89
|
+
for (let i = 0; i < node.childCount; i++) {
|
|
90
|
+
visit(node.child(i));
|
|
91
|
+
}
|
|
92
|
+
};
|
|
93
|
+
visit(tree.rootNode);
|
|
94
|
+
if (eligible.length === 0)
|
|
95
|
+
return text;
|
|
96
|
+
// Sort in reverse document order (process from bottom to top)
|
|
97
|
+
eligible.sort((a, b) => b.startPosition.row - a.startPosition.row ||
|
|
98
|
+
b.startPosition.column - a.startPosition.column);
|
|
99
|
+
let result = text;
|
|
100
|
+
for (const stateNode of eligible) {
|
|
101
|
+
const row = stateNode.startPosition.row;
|
|
102
|
+
const startCol = stateNode.startPosition.column;
|
|
103
|
+
const endCol = stateNode.endPosition.column;
|
|
104
|
+
const line = result.split("\n")[row];
|
|
105
|
+
const nodeText = line.substring(startCol, endCol);
|
|
106
|
+
// Find the state name
|
|
107
|
+
const nameNode = stateNode.childForFieldName("name");
|
|
108
|
+
if (!nameNode)
|
|
109
|
+
continue;
|
|
110
|
+
const stateName = nameNode.text;
|
|
111
|
+
// Collect transition child texts
|
|
112
|
+
const transitionTexts = [];
|
|
113
|
+
for (let i = 0; i < stateNode.childCount; i++) {
|
|
114
|
+
const child = stateNode.child(i);
|
|
115
|
+
if (child.type === "transition" || child.type === "standalone_transition") {
|
|
116
|
+
transitionTexts.push(child.text);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
// Compute the indent of the state itself (leading whitespace before it)
|
|
120
|
+
const stateIndent = line.substring(0, startCol);
|
|
121
|
+
const childIndent = stateIndent + " "; // +1 level
|
|
122
|
+
// Build expanded text
|
|
123
|
+
const expandedLines = [`${stateName} {`];
|
|
124
|
+
for (const t of transitionTexts) {
|
|
125
|
+
expandedLines.push(`${childIndent}${t}`);
|
|
126
|
+
}
|
|
127
|
+
expandedLines.push(`${stateIndent}}`);
|
|
128
|
+
const expanded = expandedLines.join("\n");
|
|
129
|
+
// Replace in the result
|
|
130
|
+
const allLines = result.split("\n");
|
|
131
|
+
allLines[row] = line.substring(0, startCol) + expanded + line.substring(endCol);
|
|
132
|
+
result = allLines.join("\n");
|
|
133
|
+
}
|
|
134
|
+
return result;
|
|
135
|
+
}
|
|
12
136
|
/**
|
|
13
|
-
*
|
|
14
|
-
* that the formatter should not re-indent).
|
|
137
|
+
* Compute indent edits for an Umple document using syntax-aware indentation.
|
|
15
138
|
*
|
|
16
|
-
* @param
|
|
139
|
+
* @param text Document text
|
|
140
|
+
* @param options Formatting options (tabSize, insertSpaces)
|
|
141
|
+
* @param tree Pre-parsed tree-sitter tree
|
|
142
|
+
* @returns Array of TextEdits to apply for correct indentation
|
|
143
|
+
*/
|
|
144
|
+
function computeIndentEdits(text, options, tree) {
|
|
145
|
+
const lines = text.split("\n");
|
|
146
|
+
const edits = [];
|
|
147
|
+
const unit = options.insertSpaces ? " ".repeat(options.tabSize) : "\t";
|
|
148
|
+
for (let i = 0; i < lines.length; i++) {
|
|
149
|
+
const line = lines[i];
|
|
150
|
+
const trimmed = line.trim();
|
|
151
|
+
// Skip empty lines
|
|
152
|
+
if (!trimmed)
|
|
153
|
+
continue;
|
|
154
|
+
// Skip lines inside verbatim regions (embedded code)
|
|
155
|
+
if ((0, formatRules_1.isVerbatimLine)(tree, i))
|
|
156
|
+
continue;
|
|
157
|
+
// Find first non-whitespace column for AST lookup
|
|
158
|
+
const firstNonWs = line.length - line.trimStart().length;
|
|
159
|
+
// Compute structural depth from AST ancestors
|
|
160
|
+
let depth = (0, formatRules_1.computeStructuralDepth)(tree, i, firstNonWs);
|
|
161
|
+
// Handle leading closing braces: outdent before indenting this line
|
|
162
|
+
let leadingCloses = 0;
|
|
163
|
+
for (const ch of trimmed) {
|
|
164
|
+
if (ch === "}")
|
|
165
|
+
leadingCloses++;
|
|
166
|
+
else
|
|
167
|
+
break;
|
|
168
|
+
}
|
|
169
|
+
depth = Math.max(0, depth - leadingCloses);
|
|
170
|
+
// Compute expected indent
|
|
171
|
+
const expected = unit.repeat(depth);
|
|
172
|
+
const currentIndent = line.substring(0, firstNonWs);
|
|
173
|
+
// Only emit edit if indent differs
|
|
174
|
+
if (currentIndent !== expected) {
|
|
175
|
+
edits.push(node_1.TextEdit.replace(node_1.Range.create(node_1.Position.create(i, 0), node_1.Position.create(i, currentIndent.length)), expected));
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
return edits;
|
|
179
|
+
}
|
|
180
|
+
// ── Phase 2: Targeted fixups ────────────────────────────────────────────────
|
|
181
|
+
/** Node types that contain a `->` arrow whose surrounding whitespace should be normalized. */
|
|
182
|
+
const ARROW_NODES = new Set(["transition", "standalone_transition"]);
|
|
183
|
+
/**
|
|
184
|
+
* Normalize whitespace around `->` in transition and standalone_transition nodes.
|
|
185
|
+
* Only handles single-line nodes. Leaves event, guard, action, and target text verbatim.
|
|
186
|
+
*/
|
|
187
|
+
function fixTransitionSpacing(text, tree) {
|
|
188
|
+
const lines = text.split("\n");
|
|
189
|
+
const edits = [];
|
|
190
|
+
const visit = (node) => {
|
|
191
|
+
if (ARROW_NODES.has(node.type)) {
|
|
192
|
+
const startRow = node.startPosition.row;
|
|
193
|
+
const endRow = node.endPosition.row;
|
|
194
|
+
// Only single-line transitions
|
|
195
|
+
if (startRow !== endRow)
|
|
196
|
+
return;
|
|
197
|
+
// Find the structural "->" token by walking children (not substring search,
|
|
198
|
+
// which would match "->" inside action_code like "foo->bar")
|
|
199
|
+
let arrowChild = null;
|
|
200
|
+
for (let c = 0; c < node.childCount; c++) {
|
|
201
|
+
const child = node.child(c);
|
|
202
|
+
if (child && child.type === "->") {
|
|
203
|
+
arrowChild = child;
|
|
204
|
+
break;
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
if (!arrowChild)
|
|
208
|
+
return;
|
|
209
|
+
const arrowCol = arrowChild.startPosition.column;
|
|
210
|
+
const arrowEndCol = arrowChild.endPosition.column;
|
|
211
|
+
const line = lines[startRow];
|
|
212
|
+
// Find whitespace region around the structural arrow
|
|
213
|
+
let wsStart = arrowCol;
|
|
214
|
+
while (wsStart > 0 && line[wsStart - 1] === " ") {
|
|
215
|
+
wsStart--;
|
|
216
|
+
}
|
|
217
|
+
let wsEnd = arrowEndCol;
|
|
218
|
+
while (wsEnd < line.length && line[wsEnd] === " ") {
|
|
219
|
+
wsEnd++;
|
|
220
|
+
}
|
|
221
|
+
const currentRegion = line.substring(wsStart, wsEnd);
|
|
222
|
+
const expectedRegion = " -> ";
|
|
223
|
+
if (currentRegion === expectedRegion)
|
|
224
|
+
return;
|
|
225
|
+
edits.push(node_1.TextEdit.replace(node_1.Range.create(node_1.Position.create(startRow, wsStart), node_1.Position.create(startRow, wsEnd)), expectedRegion));
|
|
226
|
+
return; // Don't descend into transition children
|
|
227
|
+
}
|
|
228
|
+
for (let i = 0; i < node.childCount; i++) {
|
|
229
|
+
visit(node.child(i));
|
|
230
|
+
}
|
|
231
|
+
};
|
|
232
|
+
visit(tree.rootNode);
|
|
233
|
+
return edits;
|
|
234
|
+
}
|
|
235
|
+
/** Node types that contain an `arrow` child whose surrounding whitespace should be normalized. */
|
|
236
|
+
const ASSOC_NODES = new Set(["association_inline", "association_member"]);
|
|
237
|
+
/**
|
|
238
|
+
* Normalize whitespace around the arrow in association_inline and association_member nodes.
|
|
239
|
+
* Only handles single-line nodes. Same child-walking approach as fixTransitionSpacing.
|
|
240
|
+
*/
|
|
241
|
+
function fixAssociationSpacing(text, tree) {
|
|
242
|
+
const lines = text.split("\n");
|
|
243
|
+
const edits = [];
|
|
244
|
+
const visit = (node) => {
|
|
245
|
+
if (ASSOC_NODES.has(node.type)) {
|
|
246
|
+
const startRow = node.startPosition.row;
|
|
247
|
+
const endRow = node.endPosition.row;
|
|
248
|
+
if (startRow !== endRow)
|
|
249
|
+
return;
|
|
250
|
+
// Find the "arrow" child node
|
|
251
|
+
let arrowChild = null;
|
|
252
|
+
for (let c = 0; c < node.childCount; c++) {
|
|
253
|
+
const child = node.child(c);
|
|
254
|
+
if (child && child.type === "arrow") {
|
|
255
|
+
arrowChild = child;
|
|
256
|
+
break;
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
if (!arrowChild)
|
|
260
|
+
return;
|
|
261
|
+
const arrowCol = arrowChild.startPosition.column;
|
|
262
|
+
const arrowEndCol = arrowChild.endPosition.column;
|
|
263
|
+
const line = lines[startRow];
|
|
264
|
+
// Find whitespace region around the arrow
|
|
265
|
+
let wsStart = arrowCol;
|
|
266
|
+
while (wsStart > 0 && line[wsStart - 1] === " ") {
|
|
267
|
+
wsStart--;
|
|
268
|
+
}
|
|
269
|
+
let wsEnd = arrowEndCol;
|
|
270
|
+
while (wsEnd < line.length && line[wsEnd] === " ") {
|
|
271
|
+
wsEnd++;
|
|
272
|
+
}
|
|
273
|
+
const currentRegion = line.substring(wsStart, wsEnd);
|
|
274
|
+
const arrowText = arrowChild.text;
|
|
275
|
+
const expectedRegion = " " + arrowText + " ";
|
|
276
|
+
if (currentRegion === expectedRegion)
|
|
277
|
+
return;
|
|
278
|
+
edits.push(node_1.TextEdit.replace(node_1.Range.create(node_1.Position.create(startRow, wsStart), node_1.Position.create(startRow, wsEnd)), expectedRegion));
|
|
279
|
+
return;
|
|
280
|
+
}
|
|
281
|
+
for (let i = 0; i < node.childCount; i++) {
|
|
282
|
+
visit(node.child(i));
|
|
283
|
+
}
|
|
284
|
+
};
|
|
285
|
+
visit(tree.rootNode);
|
|
286
|
+
return edits;
|
|
287
|
+
}
|
|
288
|
+
/**
|
|
289
|
+
* Normalize blank lines between top-level declarations in source_file.
|
|
290
|
+
* Ensures exactly 1 blank line between consecutive top-level named children.
|
|
291
|
+
* Does NOT touch interior body spacing.
|
|
292
|
+
*/
|
|
293
|
+
function normalizeTopLevelBlankLines(text, tree) {
|
|
294
|
+
const lines = text.split("\n");
|
|
295
|
+
const edits = [];
|
|
296
|
+
const root = tree.rootNode;
|
|
297
|
+
// Collect top-level named declaration children (skip comments and anonymous nodes)
|
|
298
|
+
const topDecls = [];
|
|
299
|
+
for (let i = 0; i < root.namedChildCount; i++) {
|
|
300
|
+
const child = root.namedChild(i);
|
|
301
|
+
if (child && formatRules_1.TOP_LEVEL_DECL_NODES.has(child.type)) {
|
|
302
|
+
topDecls.push({
|
|
303
|
+
startRow: child.startPosition.row,
|
|
304
|
+
endRow: child.endPosition.row,
|
|
305
|
+
});
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
// For each consecutive pair, ensure exactly 1 blank line between them
|
|
309
|
+
for (let i = 0; i < topDecls.length - 1; i++) {
|
|
310
|
+
const prevEnd = topDecls[i].endRow;
|
|
311
|
+
const nextStart = topDecls[i + 1].startRow;
|
|
312
|
+
const gap = nextStart - prevEnd - 1; // number of lines between them
|
|
313
|
+
if (gap === 1)
|
|
314
|
+
continue; // Already correct: exactly 1 blank line
|
|
315
|
+
// Safety: if any non-blank line exists in the gap (e.g., comments),
|
|
316
|
+
// skip this gap entirely to avoid deleting user content
|
|
317
|
+
if (gap > 1) {
|
|
318
|
+
let hasNonBlank = false;
|
|
319
|
+
for (let row = prevEnd + 1; row < nextStart; row++) {
|
|
320
|
+
if (lines[row].trim().length > 0) {
|
|
321
|
+
hasNonBlank = true;
|
|
322
|
+
break;
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
if (hasNonBlank)
|
|
326
|
+
continue;
|
|
327
|
+
}
|
|
328
|
+
if (gap < 1) {
|
|
329
|
+
// No blank line — insert at the END of the previous declaration's last line.
|
|
330
|
+
// This avoids conflicting with indent edits that target [nextStart, 0].
|
|
331
|
+
edits.push(node_1.TextEdit.insert(node_1.Position.create(prevEnd, lines[prevEnd].length), "\n"));
|
|
332
|
+
}
|
|
333
|
+
else {
|
|
334
|
+
// Too many blank lines (all blank) — remove extras (keep exactly 1)
|
|
335
|
+
const deleteStart = prevEnd + 2;
|
|
336
|
+
const deleteEnd = nextStart;
|
|
337
|
+
edits.push(node_1.TextEdit.del(node_1.Range.create(node_1.Position.create(deleteStart, 0), node_1.Position.create(deleteEnd, 0))));
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
return edits;
|
|
341
|
+
}
|
|
342
|
+
/**
|
|
343
|
+
* Collect line ranges of code_content and template_body nodes.
|
|
344
|
+
* Kept for backward compatibility with existing callers; the new
|
|
345
|
+
* formatter uses isVerbatimLine() from formatRules instead.
|
|
17
346
|
*/
|
|
18
347
|
function getCodeContentRanges(tree) {
|
|
19
348
|
const ranges = [];
|
|
@@ -48,49 +377,4 @@ function getCodeContentRanges(tree) {
|
|
|
48
377
|
}
|
|
49
378
|
return ranges;
|
|
50
379
|
}
|
|
51
|
-
function isInSkipRange(line, ranges) {
|
|
52
|
-
return ranges.some((r) => line > r.startLine && line < r.endLine);
|
|
53
|
-
}
|
|
54
|
-
/**
|
|
55
|
-
* Compute indent edits for an Umple document.
|
|
56
|
-
*
|
|
57
|
-
* @param text Document text
|
|
58
|
-
* @param options Formatting options (tabSize, insertSpaces)
|
|
59
|
-
* @param skipRanges Ranges to skip (embedded code content)
|
|
60
|
-
*/
|
|
61
|
-
function computeIndentEdits(text, options, skipRanges) {
|
|
62
|
-
const lines = text.split("\n");
|
|
63
|
-
const edits = [];
|
|
64
|
-
const unit = options.insertSpaces ? " ".repeat(options.tabSize) : "\t";
|
|
65
|
-
let depth = 0;
|
|
66
|
-
for (let i = 0; i < lines.length; i++) {
|
|
67
|
-
const line = lines[i];
|
|
68
|
-
const trimmed = line.trim();
|
|
69
|
-
if (!trimmed || isInSkipRange(i, skipRanges))
|
|
70
|
-
continue;
|
|
71
|
-
let leadingCloses = 0;
|
|
72
|
-
for (const ch of trimmed) {
|
|
73
|
-
if (ch === "}")
|
|
74
|
-
leadingCloses++;
|
|
75
|
-
else
|
|
76
|
-
break;
|
|
77
|
-
}
|
|
78
|
-
depth = Math.max(0, depth - leadingCloses);
|
|
79
|
-
const expected = unit.repeat(depth);
|
|
80
|
-
const currentIndent = line.substring(0, line.length - line.trimStart().length);
|
|
81
|
-
if (currentIndent !== expected) {
|
|
82
|
-
edits.push(node_1.TextEdit.replace(node_1.Range.create(node_1.Position.create(i, 0), node_1.Position.create(i, currentIndent.length)), expected));
|
|
83
|
-
}
|
|
84
|
-
let opens = 0;
|
|
85
|
-
let closes = 0;
|
|
86
|
-
for (const ch of trimmed) {
|
|
87
|
-
if (ch === "{")
|
|
88
|
-
opens++;
|
|
89
|
-
else if (ch === "}")
|
|
90
|
-
closes++;
|
|
91
|
-
}
|
|
92
|
-
depth = Math.max(0, depth + opens - (closes - leadingCloses));
|
|
93
|
-
}
|
|
94
|
-
return edits;
|
|
95
|
-
}
|
|
96
380
|
//# sourceMappingURL=formatter.js.map
|
package/out/formatter.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"formatter.js","sourceRoot":"","sources":["../src/formatter.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"formatter.js","sourceRoot":"","sources":["../src/formatter.ts"],"names":[],"mappings":"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"}
|