@jbearak/sight 0.12.0 → 0.13.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/dist/sight-server.js +1368 -606
- package/dist/sight-server.js.sha256 +1 -1
- package/package.json +1 -1
package/dist/sight-server.js
CHANGED
|
@@ -52,7 +52,7 @@ var package_default;
|
|
|
52
52
|
var init_package = __esm(() => {
|
|
53
53
|
package_default = {
|
|
54
54
|
name: "@jbearak/sight",
|
|
55
|
-
version: "0.
|
|
55
|
+
version: "0.13.0",
|
|
56
56
|
type: "module",
|
|
57
57
|
workspaces: [
|
|
58
58
|
"client"
|
|
@@ -633,6 +633,13 @@ function warn_unknown_key(key_path, raw_key, warn) {
|
|
|
633
633
|
message: `Unknown project config key '${key_path}.${raw_key}'; ignoring`
|
|
634
634
|
});
|
|
635
635
|
}
|
|
636
|
+
function warn_compat_collision(canonical_path, alias_path, warn) {
|
|
637
|
+
warn?.({
|
|
638
|
+
code: "normalized-key-collision",
|
|
639
|
+
key_path: canonical_path,
|
|
640
|
+
message: `Both '${canonical_path}' and compatibility alias '${alias_path}' ` + `are set; using '${canonical_path}'`
|
|
641
|
+
});
|
|
642
|
+
}
|
|
636
643
|
function normalize_severity_value(value, key_path, allowed, warn) {
|
|
637
644
|
if (typeof value !== "string") {
|
|
638
645
|
warn_invalid_value(key_path, value, warn);
|
|
@@ -734,25 +741,40 @@ function maybe_assign_object(target, key, value) {
|
|
|
734
741
|
}
|
|
735
742
|
}
|
|
736
743
|
function map_diagnostics(raw, warn) {
|
|
737
|
-
warn_unknown_keys(raw, ["enabled", "indentation", "severity"], "diagnostics", warn);
|
|
744
|
+
warn_unknown_keys(raw, ["enabled", "indentation", "severity", "undefinedVariableSeverity"], "diagnostics", warn);
|
|
738
745
|
const mapped = {};
|
|
739
746
|
assign_boolean(mapped, "enabled", raw, "enabled", "diagnostics.enabled", warn);
|
|
740
747
|
assign_boolean(mapped, "indentation", raw, "indentation", "diagnostics.indentation", warn);
|
|
741
748
|
const severity = object_value(raw, "severity", "diagnostics.severity", warn);
|
|
749
|
+
const mapped_severity = {};
|
|
750
|
+
let canonical_undefined_variable;
|
|
742
751
|
if (severity) {
|
|
743
752
|
warn_unknown_keys(severity, DIAGNOSTIC_SEVERITY_KEYS, "diagnostics.severity", warn);
|
|
744
|
-
const mapped_severity = {};
|
|
745
753
|
for (const my_key of DIAGNOSTIC_SEVERITY_KEYS) {
|
|
746
754
|
const value = pick_key(severity, my_key, warn, `diagnostics.severity.${my_key}`);
|
|
747
755
|
if (value !== undefined) {
|
|
756
|
+
if (my_key === "undefinedVariable") {
|
|
757
|
+
canonical_undefined_variable = value;
|
|
758
|
+
}
|
|
748
759
|
const normalized = normalize_severity_value(value, `diagnostics.severity.${my_key}`, SEVERITIES, warn);
|
|
749
760
|
if (normalized) {
|
|
750
761
|
mapped_severity[my_key] = normalized;
|
|
751
762
|
}
|
|
752
763
|
}
|
|
753
764
|
}
|
|
754
|
-
maybe_assign_object(mapped, "severity", mapped_severity);
|
|
755
765
|
}
|
|
766
|
+
const legacy_undefined_variable = pick_key(raw, "undefinedVariableSeverity", warn, "diagnostics.undefinedVariableSeverity");
|
|
767
|
+
if (legacy_undefined_variable !== undefined) {
|
|
768
|
+
if (canonical_undefined_variable !== undefined) {
|
|
769
|
+
warn_compat_collision("diagnostics.severity.undefinedVariable", "diagnostics.undefinedVariableSeverity", warn);
|
|
770
|
+
} else {
|
|
771
|
+
const normalized = normalize_severity_value(legacy_undefined_variable, "diagnostics.undefinedVariableSeverity", SEVERITIES, warn);
|
|
772
|
+
if (normalized) {
|
|
773
|
+
mapped_severity.undefinedVariable = normalized;
|
|
774
|
+
}
|
|
775
|
+
}
|
|
776
|
+
}
|
|
777
|
+
maybe_assign_object(mapped, "severity", mapped_severity);
|
|
756
778
|
return Object.keys(mapped).length > 0 ? mapped : undefined;
|
|
757
779
|
}
|
|
758
780
|
function map_formatting(raw, warn) {
|
|
@@ -800,7 +822,12 @@ function map_cross_file(raw, warn) {
|
|
|
800
822
|
"maxForwardDepth",
|
|
801
823
|
"maxChainDepth",
|
|
802
824
|
"maxCalleeRevalidations",
|
|
803
|
-
"
|
|
825
|
+
"maxCachedFiles",
|
|
826
|
+
"maxCachedScopes",
|
|
827
|
+
"maxCachedForwardClosures",
|
|
828
|
+
"diagnostics",
|
|
829
|
+
"missingFileSeverity",
|
|
830
|
+
"caseMismatchSeverity"
|
|
804
831
|
], "crossFile", warn);
|
|
805
832
|
const mapped = {};
|
|
806
833
|
assign_boolean(mapped, "index_workspace", raw, "indexWorkspace", "crossFile.indexWorkspace", warn);
|
|
@@ -811,10 +838,15 @@ function map_cross_file(raw, warn) {
|
|
|
811
838
|
assign_number(mapped, "max_forward_depth", raw, "maxForwardDepth", "crossFile.maxForwardDepth", warn);
|
|
812
839
|
assign_number(mapped, "max_chain_depth", raw, "maxChainDepth", "crossFile.maxChainDepth", warn);
|
|
813
840
|
assign_number(mapped, "max_callee_revalidations", raw, "maxCalleeRevalidations", "crossFile.maxCalleeRevalidations", warn);
|
|
841
|
+
assign_number(mapped, "max_cached_files", raw, "maxCachedFiles", "crossFile.maxCachedFiles", warn);
|
|
842
|
+
assign_number(mapped, "max_cached_scopes", raw, "maxCachedScopes", "crossFile.maxCachedScopes", warn);
|
|
843
|
+
assign_number(mapped, "max_cached_forward_closures", raw, "maxCachedForwardClosures", "crossFile.maxCachedForwardClosures", warn);
|
|
814
844
|
const diagnostics = object_value(raw, "diagnostics", "crossFile.diagnostics", warn);
|
|
845
|
+
const mapped_diagnostics = {};
|
|
846
|
+
let canonical_missing_file;
|
|
847
|
+
let canonical_case_mismatch;
|
|
815
848
|
if (diagnostics) {
|
|
816
849
|
warn_unknown_keys(diagnostics, ["missingFile", "maxDepth", "callSiteIdentification", "caseMismatch"], "crossFile.diagnostics", warn);
|
|
817
|
-
const mapped_diagnostics = {};
|
|
818
850
|
for (const [public_key, internal_key] of [
|
|
819
851
|
["missingFile", "missing_file"],
|
|
820
852
|
["maxDepth", "max_depth"],
|
|
@@ -823,6 +855,9 @@ function map_cross_file(raw, warn) {
|
|
|
823
855
|
const key_path = `crossFile.diagnostics.${public_key}`;
|
|
824
856
|
const value = pick_key(diagnostics, public_key, warn, key_path);
|
|
825
857
|
if (value !== undefined) {
|
|
858
|
+
if (public_key === "missingFile") {
|
|
859
|
+
canonical_missing_file = value;
|
|
860
|
+
}
|
|
826
861
|
const normalized = normalize_severity_value(value, key_path, CROSS_FILE_SEVERITIES, warn);
|
|
827
862
|
if (normalized) {
|
|
828
863
|
mapped_diagnostics[internal_key] = normalized;
|
|
@@ -832,13 +867,36 @@ function map_cross_file(raw, warn) {
|
|
|
832
867
|
const case_mismatch_key_path = "crossFile.diagnostics.caseMismatch";
|
|
833
868
|
const case_mismatch_value = pick_key(diagnostics, "caseMismatch", warn, case_mismatch_key_path);
|
|
834
869
|
if (case_mismatch_value !== undefined) {
|
|
870
|
+
canonical_case_mismatch = case_mismatch_value;
|
|
835
871
|
const normalized = normalize_severity_value(case_mismatch_value, case_mismatch_key_path, CROSS_FILE_CASE_MISMATCH_SEVERITIES, warn);
|
|
836
872
|
if (normalized) {
|
|
837
873
|
mapped_diagnostics["case_mismatch"] = normalized;
|
|
838
874
|
}
|
|
839
875
|
}
|
|
840
|
-
maybe_assign_object(mapped, "diagnostics", mapped_diagnostics);
|
|
841
876
|
}
|
|
877
|
+
const legacy_missing_file = pick_key(raw, "missingFileSeverity", warn, "crossFile.missingFileSeverity");
|
|
878
|
+
if (legacy_missing_file !== undefined) {
|
|
879
|
+
if (canonical_missing_file !== undefined) {
|
|
880
|
+
warn_compat_collision("crossFile.diagnostics.missingFile", "crossFile.missingFileSeverity", warn);
|
|
881
|
+
} else {
|
|
882
|
+
const normalized = normalize_severity_value(legacy_missing_file, "crossFile.missingFileSeverity", CROSS_FILE_SEVERITIES, warn);
|
|
883
|
+
if (normalized) {
|
|
884
|
+
mapped_diagnostics.missing_file = normalized;
|
|
885
|
+
}
|
|
886
|
+
}
|
|
887
|
+
}
|
|
888
|
+
const legacy_case_mismatch = pick_key(raw, "caseMismatchSeverity", warn, "crossFile.caseMismatchSeverity");
|
|
889
|
+
if (legacy_case_mismatch !== undefined) {
|
|
890
|
+
if (canonical_case_mismatch !== undefined) {
|
|
891
|
+
warn_compat_collision("crossFile.diagnostics.caseMismatch", "crossFile.caseMismatchSeverity", warn);
|
|
892
|
+
} else {
|
|
893
|
+
const normalized = normalize_severity_value(legacy_case_mismatch, "crossFile.caseMismatchSeverity", CROSS_FILE_CASE_MISMATCH_SEVERITIES, warn);
|
|
894
|
+
if (normalized) {
|
|
895
|
+
mapped_diagnostics.case_mismatch = normalized;
|
|
896
|
+
}
|
|
897
|
+
}
|
|
898
|
+
}
|
|
899
|
+
maybe_assign_object(mapped, "diagnostics", mapped_diagnostics);
|
|
842
900
|
return Object.keys(mapped).length > 0 ? mapped : undefined;
|
|
843
901
|
}
|
|
844
902
|
function map_public_config_to_partial_config(raw, warn) {
|
|
@@ -857,12 +915,21 @@ function map_public_config_to_partial_config(raw, warn) {
|
|
|
857
915
|
warn_invalid_value("adoPaths", ado_paths, warn);
|
|
858
916
|
}
|
|
859
917
|
}
|
|
860
|
-
const
|
|
918
|
+
const workspace = object_value(raw, "workspace", "workspace", warn);
|
|
919
|
+
if (workspace) {
|
|
920
|
+
warn_unknown_keys(workspace, ["exclude"], "workspace", warn);
|
|
921
|
+
}
|
|
922
|
+
const canonical_exclude = workspace ? pick_key(workspace, "exclude", warn, "workspace.exclude") : undefined;
|
|
923
|
+
const legacy_exclude = pick_key(raw, "exclude", warn, "exclude");
|
|
924
|
+
const exclude = canonical_exclude !== undefined ? canonical_exclude : legacy_exclude;
|
|
925
|
+
if (canonical_exclude !== undefined && legacy_exclude !== undefined) {
|
|
926
|
+
warn_compat_collision("workspace.exclude", "exclude", warn);
|
|
927
|
+
}
|
|
861
928
|
if (exclude !== undefined) {
|
|
862
929
|
if (Array.isArray(exclude) && exclude.every((item) => typeof item === "string")) {
|
|
863
930
|
mapped.exclude = exclude;
|
|
864
931
|
} else {
|
|
865
|
-
warn_invalid_value("exclude", exclude, warn);
|
|
932
|
+
warn_invalid_value(canonical_exclude !== undefined ? "workspace.exclude" : "exclude", exclude, warn);
|
|
866
933
|
}
|
|
867
934
|
}
|
|
868
935
|
assign_string_member(root, "lineCommentStyle", raw, "lineCommentStyle", "lineCommentStyle", LINE_COMMENT_STYLES, warn);
|
|
@@ -941,6 +1008,7 @@ var init_schema = __esm(() => {
|
|
|
941
1008
|
"indexWorkspace",
|
|
942
1009
|
"adoPaths",
|
|
943
1010
|
"exclude",
|
|
1011
|
+
"workspace",
|
|
944
1012
|
"lineCommentStyle",
|
|
945
1013
|
"debug",
|
|
946
1014
|
"diagnostics",
|
|
@@ -12199,13 +12267,6 @@ class StataLexer {
|
|
|
12199
12267
|
while (this.peek() === " " || this.peek() === "\t" || this.peek() === "\r") {
|
|
12200
12268
|
this.advance();
|
|
12201
12269
|
}
|
|
12202
|
-
if (this.state.delimiterMode === "semicolon") {
|
|
12203
|
-
return {
|
|
12204
|
-
type: "WHITESPACE",
|
|
12205
|
-
value: this.source.substring(this.position_to_offset(startLine, startColumn), this.position),
|
|
12206
|
-
range: this.makeRange(startLine, startColumn, this.line, this.column)
|
|
12207
|
-
};
|
|
12208
|
-
}
|
|
12209
12270
|
return null;
|
|
12210
12271
|
}
|
|
12211
12272
|
if (char === `
|
|
@@ -12214,17 +12275,11 @@ class StataLexer {
|
|
|
12214
12275
|
return {
|
|
12215
12276
|
type: "STATEMENT_TERMINATOR",
|
|
12216
12277
|
value: `
|
|
12217
|
-
`,
|
|
12218
|
-
range: this.makeRange(startLine, startColumn, this.line, this.column)
|
|
12219
|
-
};
|
|
12220
|
-
} else {
|
|
12221
|
-
return {
|
|
12222
|
-
type: "WHITESPACE",
|
|
12223
|
-
value: `
|
|
12224
12278
|
`,
|
|
12225
12279
|
range: this.makeRange(startLine, startColumn, this.line, this.column)
|
|
12226
12280
|
};
|
|
12227
12281
|
}
|
|
12282
|
+
return null;
|
|
12228
12283
|
}
|
|
12229
12284
|
if (char === ";") {
|
|
12230
12285
|
if (this.state.delimiterMode === "semicolon") {
|
|
@@ -13205,6 +13260,34 @@ function is_swallowed_continuation_terminator(my_token, in_continuation) {
|
|
|
13205
13260
|
}
|
|
13206
13261
|
|
|
13207
13262
|
// src/parser/index.ts
|
|
13263
|
+
class ContinuationTracker {
|
|
13264
|
+
required_line = -1;
|
|
13265
|
+
prev_collected_line = null;
|
|
13266
|
+
prev_collected_end = null;
|
|
13267
|
+
chain_clean = true;
|
|
13268
|
+
note_continuation(continuation_token) {
|
|
13269
|
+
const cont_line = continuation_token.range.start.line;
|
|
13270
|
+
if (cont_line !== this.required_line) {
|
|
13271
|
+
return;
|
|
13272
|
+
}
|
|
13273
|
+
const cont_col = continuation_token.range.start.character;
|
|
13274
|
+
const is_first_on_prev_line = this.prev_collected_end !== null && this.required_line === this.prev_collected_line && cont_line === this.prev_collected_end.line;
|
|
13275
|
+
const has_leading_gap = is_first_on_prev_line ? cont_col > this.prev_collected_end.character : cont_col > 0;
|
|
13276
|
+
if (has_leading_gap) {
|
|
13277
|
+
this.chain_clean = false;
|
|
13278
|
+
}
|
|
13279
|
+
this.required_line += 1;
|
|
13280
|
+
}
|
|
13281
|
+
collect(token) {
|
|
13282
|
+
const token_line = token.range.start.line;
|
|
13283
|
+
const follows_continuation = this.prev_collected_line !== null && token_line > this.prev_collected_line && token_line === this.required_line && this.chain_clean;
|
|
13284
|
+
this.prev_collected_line = token_line;
|
|
13285
|
+
this.prev_collected_end = token.range.end;
|
|
13286
|
+
this.required_line = token_line;
|
|
13287
|
+
this.chain_clean = true;
|
|
13288
|
+
return follows_continuation;
|
|
13289
|
+
}
|
|
13290
|
+
}
|
|
13208
13291
|
var PREFIX_COMMANDS, StataParser;
|
|
13209
13292
|
var init_parser = __esm(() => {
|
|
13210
13293
|
init_types();
|
|
@@ -13274,7 +13357,7 @@ var init_parser = __esm(() => {
|
|
|
13274
13357
|
node = this.parseEmbeddedLanguageBlock("python");
|
|
13275
13358
|
} else if (this.check("WORD") && this.isPrefixCommand(this.peek().value)) {
|
|
13276
13359
|
node = this.parseCommand();
|
|
13277
|
-
} else if (this.checkWord("program") && this.
|
|
13360
|
+
} else if (this.checkWord("program") && this.tokens[this.current + 1]?.value === "define") {
|
|
13278
13361
|
node = this.parseProgramDefinition();
|
|
13279
13362
|
} else if (this.checkWord("syntax")) {
|
|
13280
13363
|
node = this.parseSyntaxCommand();
|
|
@@ -13408,9 +13491,18 @@ var init_parser = __esm(() => {
|
|
|
13408
13491
|
content += my_token.value;
|
|
13409
13492
|
if (i < content_tokens.length - 1) {
|
|
13410
13493
|
const next_token = content_tokens[i + 1];
|
|
13411
|
-
|
|
13412
|
-
|
|
13413
|
-
|
|
13494
|
+
if (next_token.range.start.line === my_token.range.end.line) {
|
|
13495
|
+
const gap = next_token.range.start.character - my_token.range.end.character;
|
|
13496
|
+
if (gap > 0) {
|
|
13497
|
+
content += " ".repeat(gap);
|
|
13498
|
+
}
|
|
13499
|
+
} else if (next_token.range.start.line > my_token.range.end.line) {
|
|
13500
|
+
const line_gap = next_token.range.start.line - my_token.range.end.line;
|
|
13501
|
+
content += `
|
|
13502
|
+
`.repeat(line_gap);
|
|
13503
|
+
if (next_token.range.start.character > 0) {
|
|
13504
|
+
content += " ".repeat(next_token.range.start.character);
|
|
13505
|
+
}
|
|
13414
13506
|
}
|
|
13415
13507
|
}
|
|
13416
13508
|
}
|
|
@@ -13449,12 +13541,20 @@ var init_parser = __esm(() => {
|
|
|
13449
13541
|
const body = [];
|
|
13450
13542
|
const was_inside_program = this.inside_program;
|
|
13451
13543
|
this.inside_program = true;
|
|
13452
|
-
while (!this.isAtEnd()
|
|
13544
|
+
while (!this.isAtEnd()) {
|
|
13545
|
+
const my_trivia = this.collectTrivia();
|
|
13546
|
+
if (my_trivia.length > 0) {
|
|
13547
|
+
this.pending_trivia.push(...my_trivia);
|
|
13548
|
+
}
|
|
13549
|
+
if (this.checkWord("end") || this.isAtEnd()) {
|
|
13550
|
+
break;
|
|
13551
|
+
}
|
|
13453
13552
|
const stmt = this.parseStatement();
|
|
13454
13553
|
if (stmt) {
|
|
13455
13554
|
body.push(stmt);
|
|
13456
13555
|
}
|
|
13457
13556
|
}
|
|
13557
|
+
const program_block_ending_trivia = this.checkWord("end") ? this.drainBlockEndingTrivia() : undefined;
|
|
13458
13558
|
this.inside_program = was_inside_program;
|
|
13459
13559
|
if (this.checkWord("end")) {
|
|
13460
13560
|
this.advance();
|
|
@@ -13467,7 +13567,8 @@ var init_parser = __esm(() => {
|
|
|
13467
13567
|
name: program_name,
|
|
13468
13568
|
body,
|
|
13469
13569
|
signature: merged_signature,
|
|
13470
|
-
range: this.makeRange(start_token.range.start, this.previous().range.end)
|
|
13570
|
+
range: this.makeRange(start_token.range.start, this.previous().range.end),
|
|
13571
|
+
blockEndingTrivia: program_block_ending_trivia
|
|
13471
13572
|
};
|
|
13472
13573
|
}
|
|
13473
13574
|
extract_and_merge_signatures(body) {
|
|
@@ -13538,20 +13639,20 @@ var init_parser = __esm(() => {
|
|
|
13538
13639
|
let paren_depth = 0;
|
|
13539
13640
|
const value_tokens = [];
|
|
13540
13641
|
const preceded_by_continuation = [];
|
|
13541
|
-
|
|
13642
|
+
const continuation = new ContinuationTracker;
|
|
13542
13643
|
while (!this.check("STATEMENT_TERMINATOR") && !this.isAtEnd()) {
|
|
13543
|
-
if (this.
|
|
13544
|
-
|
|
13545
|
-
|
|
13644
|
+
if (this.check("CONTINUATION")) {
|
|
13645
|
+
const cont_token = this.peek();
|
|
13646
|
+
if (this.skipContinuation()) {
|
|
13647
|
+
continuation.note_continuation(cont_token);
|
|
13648
|
+
continue;
|
|
13649
|
+
}
|
|
13546
13650
|
}
|
|
13547
13651
|
const token_type = this.peek().type;
|
|
13548
13652
|
if (token_type === "COMMENT_LINE" || token_type === "COMMENT_BLOCK") {
|
|
13549
13653
|
break;
|
|
13550
13654
|
}
|
|
13551
13655
|
const token = this.advance();
|
|
13552
|
-
if (token.type === "WHITESPACE") {
|
|
13553
|
-
continue;
|
|
13554
|
-
}
|
|
13555
13656
|
if (token.type === "LPAREN") {
|
|
13556
13657
|
paren_depth++;
|
|
13557
13658
|
} else if (token.type === "RPAREN") {
|
|
@@ -13562,8 +13663,7 @@ var init_parser = __esm(() => {
|
|
|
13562
13663
|
}
|
|
13563
13664
|
}
|
|
13564
13665
|
value_tokens.push(token);
|
|
13565
|
-
preceded_by_continuation.push(
|
|
13566
|
-
continuation_pending = false;
|
|
13666
|
+
preceded_by_continuation.push(continuation.collect(token));
|
|
13567
13667
|
}
|
|
13568
13668
|
const value = prefix_value + this.reconstruct_value_tokens(value_tokens, preceded_by_continuation);
|
|
13569
13669
|
if (paren_depth > 0) {
|
|
@@ -13593,17 +13693,26 @@ var init_parser = __esm(() => {
|
|
|
13593
13693
|
const function_name = this.advance().value;
|
|
13594
13694
|
this.skipMacroDefinitionTrivia();
|
|
13595
13695
|
const arg_tokens = [];
|
|
13696
|
+
const value_tokens = [];
|
|
13697
|
+
const preceded_by_continuation = [];
|
|
13698
|
+
const continuation = new ContinuationTracker;
|
|
13596
13699
|
while (!this.check("STATEMENT_TERMINATOR") && !this.isAtEnd()) {
|
|
13597
|
-
if (this.
|
|
13598
|
-
|
|
13700
|
+
if (this.check("CONTINUATION")) {
|
|
13701
|
+
const cont_token = this.peek();
|
|
13702
|
+
if (this.skipContinuation()) {
|
|
13703
|
+
continuation.note_continuation(cont_token);
|
|
13704
|
+
continue;
|
|
13705
|
+
}
|
|
13599
13706
|
}
|
|
13600
13707
|
if (this.check("COMMENT_LINE") || this.check("COMMENT_BLOCK")) {
|
|
13601
13708
|
break;
|
|
13602
13709
|
}
|
|
13603
13710
|
const token = this.advance();
|
|
13604
13711
|
arg_tokens.push(token);
|
|
13712
|
+
value_tokens.push(token);
|
|
13713
|
+
preceded_by_continuation.push(continuation.collect(token));
|
|
13605
13714
|
}
|
|
13606
|
-
const args_trimmed = this.
|
|
13715
|
+
const args_trimmed = this.reconstruct_value_tokens(value_tokens, preceded_by_continuation).trim();
|
|
13607
13716
|
const extended_function = {
|
|
13608
13717
|
name: function_name,
|
|
13609
13718
|
args: args_trimmed,
|
|
@@ -13742,12 +13851,8 @@ var init_parser = __esm(() => {
|
|
|
13742
13851
|
const has_condition_before = lbrace_token.range.start.line === command_start_line;
|
|
13743
13852
|
this.validate_open_brace(lbrace_token, lbrace_index, has_condition_before);
|
|
13744
13853
|
const body = [];
|
|
13745
|
-
|
|
13746
|
-
|
|
13747
|
-
if (stmt) {
|
|
13748
|
-
body.push(stmt);
|
|
13749
|
-
}
|
|
13750
|
-
}
|
|
13854
|
+
const { body: my_body, blockEndingTrivia } = this.parseBraceBody();
|
|
13855
|
+
body.push(...my_body);
|
|
13751
13856
|
if (this.check("RBRACE")) {
|
|
13752
13857
|
const rbrace_index = this.current;
|
|
13753
13858
|
const rbrace_token = this.advance();
|
|
@@ -13760,7 +13865,8 @@ var init_parser = __esm(() => {
|
|
|
13760
13865
|
fullName: "{",
|
|
13761
13866
|
expression: undefined,
|
|
13762
13867
|
body,
|
|
13763
|
-
range: this.makeRange(start_token.range.start, this.previous().range.end)
|
|
13868
|
+
range: this.makeRange(start_token.range.start, this.previous().range.end),
|
|
13869
|
+
blockEndingTrivia
|
|
13764
13870
|
};
|
|
13765
13871
|
}
|
|
13766
13872
|
if (!this.check("WORD") && !this.check("MACRO_REF_LOCAL") && !this.check("MACRO_REF_GLOBAL")) {
|
|
@@ -13782,24 +13888,25 @@ var init_parser = __esm(() => {
|
|
|
13782
13888
|
if (commandName === "args") {
|
|
13783
13889
|
return this.parseArgsCommand(command_token, prefixes);
|
|
13784
13890
|
}
|
|
13785
|
-
if (commandName === "frame"
|
|
13891
|
+
if (commandName === "frame") {
|
|
13786
13892
|
const saved_pos = this.current;
|
|
13787
|
-
|
|
13788
|
-
|
|
13789
|
-
|
|
13790
|
-
this.
|
|
13791
|
-
|
|
13792
|
-
|
|
13793
|
-
|
|
13794
|
-
|
|
13795
|
-
|
|
13796
|
-
|
|
13797
|
-
|
|
13798
|
-
|
|
13799
|
-
|
|
13800
|
-
|
|
13801
|
-
|
|
13893
|
+
if (this.check("WORD")) {
|
|
13894
|
+
const frame_name_token = this.advance();
|
|
13895
|
+
this.skipTrivia();
|
|
13896
|
+
if (this.check("COLON")) {
|
|
13897
|
+
this.advance();
|
|
13898
|
+
const frame_prefix = {
|
|
13899
|
+
type: "prefix",
|
|
13900
|
+
name: "frame",
|
|
13901
|
+
fullName: "frame",
|
|
13902
|
+
frameName: frame_name_token.value,
|
|
13903
|
+
has_colon: true,
|
|
13904
|
+
range: this.makeRange(command_token.range.start, this.previous().range.end)
|
|
13905
|
+
};
|
|
13906
|
+
return this.parseFramePrefixedCommand(frame_prefix, prefixes, start_token);
|
|
13907
|
+
}
|
|
13802
13908
|
}
|
|
13909
|
+
this.current = saved_pos;
|
|
13803
13910
|
}
|
|
13804
13911
|
return this.parseCommandBody(command_token, prefixes, start_token);
|
|
13805
13912
|
}
|
|
@@ -13917,6 +14024,9 @@ var init_parser = __esm(() => {
|
|
|
13917
14024
|
const parsed = this.parse_option_argument_inside_parens();
|
|
13918
14025
|
option.argument = parsed.argument;
|
|
13919
14026
|
option.argument_range = parsed.argument_range;
|
|
14027
|
+
if (parsed.argument_unclosed) {
|
|
14028
|
+
option.argument_unclosed = true;
|
|
14029
|
+
}
|
|
13920
14030
|
}
|
|
13921
14031
|
options.push(option);
|
|
13922
14032
|
} else {
|
|
@@ -13939,19 +14049,41 @@ var init_parser = __esm(() => {
|
|
|
13939
14049
|
}
|
|
13940
14050
|
parse_option_argument_inside_parens() {
|
|
13941
14051
|
this.advance();
|
|
13942
|
-
let argument = "";
|
|
13943
14052
|
const arg_tokens = [];
|
|
13944
|
-
|
|
14053
|
+
const preceded_by_continuation = [];
|
|
14054
|
+
const continuation = new ContinuationTracker;
|
|
14055
|
+
let paren_depth = 1;
|
|
14056
|
+
while (!this.isAtEnd() && paren_depth > 0) {
|
|
14057
|
+
if (this.check("STATEMENT_TERMINATOR")) {
|
|
14058
|
+
break;
|
|
14059
|
+
}
|
|
14060
|
+
if (this.check("CONTINUATION")) {
|
|
14061
|
+
const cont_token = this.peek();
|
|
14062
|
+
if (this.skipContinuation()) {
|
|
14063
|
+
continuation.note_continuation(cont_token);
|
|
14064
|
+
continue;
|
|
14065
|
+
}
|
|
14066
|
+
}
|
|
14067
|
+
if (this.check("COMMENT_LINE") || this.check("COMMENT_BLOCK")) {
|
|
14068
|
+
this.advance();
|
|
14069
|
+
continue;
|
|
14070
|
+
}
|
|
13945
14071
|
const t = this.advance();
|
|
14072
|
+
if (t.type === "LPAREN") {
|
|
14073
|
+
paren_depth++;
|
|
14074
|
+
} else if (t.type === "RPAREN") {
|
|
14075
|
+
paren_depth--;
|
|
14076
|
+
if (paren_depth === 0) {
|
|
14077
|
+
break;
|
|
14078
|
+
}
|
|
14079
|
+
}
|
|
13946
14080
|
arg_tokens.push(t);
|
|
13947
|
-
|
|
14081
|
+
preceded_by_continuation.push(continuation.collect(t));
|
|
13948
14082
|
}
|
|
13949
|
-
|
|
13950
|
-
|
|
13951
|
-
}
|
|
13952
|
-
|
|
13953
|
-
const argument_range = non_ws.length > 0 ? { start: non_ws[0].range.start, end: non_ws[non_ws.length - 1].range.end } : undefined;
|
|
13954
|
-
return { argument, argument_range };
|
|
14083
|
+
const argument_unclosed = paren_depth > 0 ? true : undefined;
|
|
14084
|
+
const argument = this.reconstruct_value_tokens(arg_tokens, preceded_by_continuation);
|
|
14085
|
+
const argument_range = arg_tokens.length > 0 ? { start: arg_tokens[0].range.start, end: arg_tokens[arg_tokens.length - 1].range.end } : undefined;
|
|
14086
|
+
return { argument, argument_range, argument_unclosed };
|
|
13955
14087
|
}
|
|
13956
14088
|
parseFilePathArgument() {
|
|
13957
14089
|
if (this.check("STRING")) {
|
|
@@ -13967,13 +14099,18 @@ var init_parser = __esm(() => {
|
|
|
13967
14099
|
const start_token = this.advance();
|
|
13968
14100
|
let path3 = start_token.value;
|
|
13969
14101
|
let end_range = start_token.range.end;
|
|
14102
|
+
let prev_token = start_token;
|
|
13970
14103
|
while (!this.isAtEnd()) {
|
|
13971
|
-
if (this.check("
|
|
14104
|
+
if (this.check("COMMA") || this.check("STATEMENT_TERMINATOR") || this.isTrivia()) {
|
|
14105
|
+
break;
|
|
14106
|
+
}
|
|
14107
|
+
if (!this.isAdjacentToken(prev_token, this.peek())) {
|
|
13972
14108
|
break;
|
|
13973
14109
|
}
|
|
13974
14110
|
const token = this.advance();
|
|
13975
14111
|
path3 += token.value;
|
|
13976
14112
|
end_range = token.range.end;
|
|
14113
|
+
prev_token = token;
|
|
13977
14114
|
}
|
|
13978
14115
|
return {
|
|
13979
14116
|
name: path3,
|
|
@@ -13982,39 +14119,56 @@ var init_parser = __esm(() => {
|
|
|
13982
14119
|
}
|
|
13983
14120
|
parseParenthesizedGroup() {
|
|
13984
14121
|
const paren_start = this.advance();
|
|
13985
|
-
const
|
|
14122
|
+
const inner_tokens = [];
|
|
14123
|
+
const preceded_by_continuation = [];
|
|
14124
|
+
const continuation = new ContinuationTracker;
|
|
13986
14125
|
let paren_depth = 1;
|
|
13987
|
-
|
|
14126
|
+
const collect = (my_token) => {
|
|
14127
|
+
inner_tokens.push(my_token);
|
|
14128
|
+
preceded_by_continuation.push(continuation.collect(my_token));
|
|
14129
|
+
};
|
|
13988
14130
|
while (!this.isAtEnd() && paren_depth > 0) {
|
|
14131
|
+
if (this.check("STATEMENT_TERMINATOR")) {
|
|
14132
|
+
break;
|
|
14133
|
+
}
|
|
14134
|
+
if (this.check("CONTINUATION")) {
|
|
14135
|
+
const cont_token = this.peek();
|
|
14136
|
+
if (this.skipContinuation()) {
|
|
14137
|
+
continuation.note_continuation(cont_token);
|
|
14138
|
+
continue;
|
|
14139
|
+
}
|
|
14140
|
+
}
|
|
13989
14141
|
if (this.check("LPAREN")) {
|
|
13990
14142
|
paren_depth++;
|
|
13991
|
-
|
|
13992
|
-
last_was_word = false;
|
|
14143
|
+
collect(this.advance());
|
|
13993
14144
|
} else if (this.check("RPAREN")) {
|
|
13994
14145
|
paren_depth--;
|
|
13995
14146
|
if (paren_depth > 0) {
|
|
13996
|
-
|
|
14147
|
+
collect(this.advance());
|
|
13997
14148
|
}
|
|
13998
|
-
last_was_word = false;
|
|
13999
14149
|
} else {
|
|
14000
|
-
|
|
14001
|
-
if (last_was_word && current_is_word) {
|
|
14002
|
-
paren_parts.push(" ");
|
|
14003
|
-
}
|
|
14004
|
-
paren_parts.push(this.advance().value);
|
|
14005
|
-
last_was_word = current_is_word;
|
|
14150
|
+
collect(this.advance());
|
|
14006
14151
|
}
|
|
14007
14152
|
}
|
|
14008
|
-
const paren_content =
|
|
14009
|
-
const
|
|
14010
|
-
|
|
14153
|
+
const paren_content = this.reconstruct_value_tokens(inner_tokens, preceded_by_continuation);
|
|
14154
|
+
const closed_group = paren_depth === 0 && this.check("RPAREN");
|
|
14155
|
+
const paren_end_pos = closed_group ? this.peek().range.end : this.previous().range.end;
|
|
14156
|
+
if (closed_group) {
|
|
14011
14157
|
this.advance();
|
|
14012
14158
|
}
|
|
14013
14159
|
if (!paren_content.trim()) {
|
|
14014
|
-
|
|
14160
|
+
if (closed_group) {
|
|
14161
|
+
return null;
|
|
14162
|
+
}
|
|
14163
|
+
return {
|
|
14164
|
+
name: "(",
|
|
14165
|
+
recovery_only: true,
|
|
14166
|
+
range: this.makeRange(paren_start.range.start, paren_end_pos)
|
|
14167
|
+
};
|
|
14015
14168
|
}
|
|
14169
|
+
const group_name = closed_group ? `(${paren_content})` : `(${paren_content}`;
|
|
14016
14170
|
return {
|
|
14017
|
-
name:
|
|
14171
|
+
name: group_name,
|
|
14018
14172
|
range: this.makeRange(paren_start.range.start, paren_end_pos)
|
|
14019
14173
|
};
|
|
14020
14174
|
}
|
|
@@ -14071,6 +14225,9 @@ var init_parser = __esm(() => {
|
|
|
14071
14225
|
const parsed = this.parse_option_argument_inside_parens();
|
|
14072
14226
|
option.argument = parsed.argument;
|
|
14073
14227
|
option.argument_range = parsed.argument_range;
|
|
14228
|
+
if (parsed.argument_unclosed) {
|
|
14229
|
+
option.argument_unclosed = true;
|
|
14230
|
+
}
|
|
14074
14231
|
}
|
|
14075
14232
|
options.push(option);
|
|
14076
14233
|
} else {
|
|
@@ -14123,8 +14280,22 @@ var init_parser = __esm(() => {
|
|
|
14123
14280
|
let allows_arbitrary_options = false;
|
|
14124
14281
|
const seen_option_names = new Set;
|
|
14125
14282
|
const syntax_tokens = [];
|
|
14126
|
-
|
|
14127
|
-
|
|
14283
|
+
const preceded_by_continuation = [];
|
|
14284
|
+
const continuation = new ContinuationTracker;
|
|
14285
|
+
while (!this.check("STATEMENT_TERMINATOR") && !this.isAtEnd()) {
|
|
14286
|
+
if (this.check("CONTINUATION")) {
|
|
14287
|
+
const cont_token = this.peek();
|
|
14288
|
+
if (this.skipContinuation()) {
|
|
14289
|
+
continuation.note_continuation(cont_token);
|
|
14290
|
+
continue;
|
|
14291
|
+
}
|
|
14292
|
+
}
|
|
14293
|
+
if (this.check("COMMENT_LINE") || this.check("COMMENT_BLOCK")) {
|
|
14294
|
+
break;
|
|
14295
|
+
}
|
|
14296
|
+
const my_token = this.advance();
|
|
14297
|
+
syntax_tokens.push(my_token);
|
|
14298
|
+
preceded_by_continuation.push(continuation.collect(my_token));
|
|
14128
14299
|
}
|
|
14129
14300
|
let token_idx = 0;
|
|
14130
14301
|
while (token_idx < syntax_tokens.length) {
|
|
@@ -14145,7 +14316,7 @@ var init_parser = __esm(() => {
|
|
|
14145
14316
|
const my_token = syntax_tokens[token_idx];
|
|
14146
14317
|
if (my_token.type === "OPERATOR" && my_token.value === "*") {
|
|
14147
14318
|
if (token_idx + 1 < syntax_tokens.length && syntax_tokens[token_idx + 1].type === "WORD") {
|
|
14148
|
-
const opt_result2 = this.parse_option_spec(syntax_tokens, token_idx);
|
|
14319
|
+
const opt_result2 = this.parse_option_spec(syntax_tokens, token_idx, preceded_by_continuation);
|
|
14149
14320
|
if (opt_result2) {
|
|
14150
14321
|
const opt_name_lower = opt_result2.spec.name;
|
|
14151
14322
|
seen_option_names.add(opt_name_lower);
|
|
@@ -14160,7 +14331,7 @@ var init_parser = __esm(() => {
|
|
|
14160
14331
|
}
|
|
14161
14332
|
continue;
|
|
14162
14333
|
}
|
|
14163
|
-
const opt_result = this.parse_option_spec(syntax_tokens, token_idx);
|
|
14334
|
+
const opt_result = this.parse_option_spec(syntax_tokens, token_idx, preceded_by_continuation);
|
|
14164
14335
|
if (opt_result) {
|
|
14165
14336
|
const opt_name_lower = opt_result.spec.name;
|
|
14166
14337
|
seen_option_names.add(opt_name_lower);
|
|
@@ -14269,7 +14440,7 @@ var init_parser = __esm(() => {
|
|
|
14269
14440
|
};
|
|
14270
14441
|
return { spec, next_idx: current_idx };
|
|
14271
14442
|
}
|
|
14272
|
-
parse_option_spec(tokens, start_idx) {
|
|
14443
|
+
parse_option_spec(tokens, start_idx, preceded_by_continuation = []) {
|
|
14273
14444
|
if (start_idx >= tokens.length) {
|
|
14274
14445
|
return null;
|
|
14275
14446
|
}
|
|
@@ -14302,6 +14473,7 @@ var init_parser = __esm(() => {
|
|
|
14302
14473
|
if (current_idx < tokens.length && tokens[current_idx].type === "LPAREN") {
|
|
14303
14474
|
current_idx++;
|
|
14304
14475
|
const type_tokens = [];
|
|
14476
|
+
const type_flags = [];
|
|
14305
14477
|
let paren_depth = 1;
|
|
14306
14478
|
while (current_idx < tokens.length && paren_depth > 0) {
|
|
14307
14479
|
const my_token = tokens[current_idx];
|
|
@@ -14314,6 +14486,7 @@ var init_parser = __esm(() => {
|
|
|
14314
14486
|
}
|
|
14315
14487
|
}
|
|
14316
14488
|
type_tokens.push(my_token);
|
|
14489
|
+
type_flags.push(preceded_by_continuation[current_idx] ?? false);
|
|
14317
14490
|
current_idx++;
|
|
14318
14491
|
}
|
|
14319
14492
|
if (current_idx < tokens.length && tokens[current_idx].type === "RPAREN") {
|
|
@@ -14336,25 +14509,25 @@ var init_parser = __esm(() => {
|
|
|
14336
14509
|
argument_type = first_part;
|
|
14337
14510
|
for (let i = 1;i < type_tokens.length; i++) {
|
|
14338
14511
|
if (type_tokens[i].type === "WORD" && type_tokens[i].value === "default" && i + 1 < type_tokens.length && type_tokens[i + 1].type === "LPAREN") {
|
|
14339
|
-
|
|
14512
|
+
const default_tokens = [];
|
|
14513
|
+
const default_flags = [];
|
|
14340
14514
|
let default_paren_depth = 1;
|
|
14341
14515
|
let j = i + 2;
|
|
14342
14516
|
while (j < type_tokens.length && default_paren_depth > 0) {
|
|
14343
14517
|
const my_token = type_tokens[j];
|
|
14344
14518
|
if (my_token.type === "LPAREN") {
|
|
14345
14519
|
default_paren_depth++;
|
|
14346
|
-
default_str += my_token.value;
|
|
14347
14520
|
} else if (my_token.type === "RPAREN") {
|
|
14348
14521
|
default_paren_depth--;
|
|
14349
|
-
if (default_paren_depth
|
|
14350
|
-
|
|
14522
|
+
if (default_paren_depth === 0) {
|
|
14523
|
+
break;
|
|
14351
14524
|
}
|
|
14352
|
-
} else {
|
|
14353
|
-
default_str += my_token.value;
|
|
14354
14525
|
}
|
|
14526
|
+
default_tokens.push(my_token);
|
|
14527
|
+
default_flags.push(type_flags[j] ?? false);
|
|
14355
14528
|
j++;
|
|
14356
14529
|
}
|
|
14357
|
-
default_value =
|
|
14530
|
+
default_value = this.reconstruct_value_tokens(default_tokens, default_flags).trim();
|
|
14358
14531
|
break;
|
|
14359
14532
|
}
|
|
14360
14533
|
}
|
|
@@ -14455,11 +14628,17 @@ var init_parser = __esm(() => {
|
|
|
14455
14628
|
parseIfStatement() {
|
|
14456
14629
|
const ifToken = this.advance();
|
|
14457
14630
|
const condition_tokens = [];
|
|
14631
|
+
const preceded_by_continuation = [];
|
|
14632
|
+
const continuation = new ContinuationTracker;
|
|
14458
14633
|
const condition_start_line = ifToken.range.start.line;
|
|
14459
14634
|
let paren_depth = 0;
|
|
14460
14635
|
while (!this.check("LBRACE") && !this.isAtEnd()) {
|
|
14461
|
-
if (this.
|
|
14462
|
-
|
|
14636
|
+
if (this.check("CONTINUATION")) {
|
|
14637
|
+
const cont_token = this.peek();
|
|
14638
|
+
if (this.skipContinuation()) {
|
|
14639
|
+
continuation.note_continuation(cont_token);
|
|
14640
|
+
continue;
|
|
14641
|
+
}
|
|
14463
14642
|
}
|
|
14464
14643
|
if (this.check("STATEMENT_TERMINATOR")) {
|
|
14465
14644
|
break;
|
|
@@ -14474,11 +14653,10 @@ var init_parser = __esm(() => {
|
|
|
14474
14653
|
paren_depth = 0;
|
|
14475
14654
|
}
|
|
14476
14655
|
}
|
|
14477
|
-
|
|
14478
|
-
|
|
14479
|
-
}
|
|
14656
|
+
condition_tokens.push(token);
|
|
14657
|
+
preceded_by_continuation.push(continuation.collect(token));
|
|
14480
14658
|
}
|
|
14481
|
-
const condition = this.
|
|
14659
|
+
const condition = this.reconstruct_value_tokens(condition_tokens, preceded_by_continuation).trim();
|
|
14482
14660
|
if (paren_depth > 0) {
|
|
14483
14661
|
this.addError("Unbalanced parentheses in if condition: missing closing parenthesis", ifToken.range, "UNBALANCED_PARENTHESES" /* UNBALANCED_PARENTHESES */);
|
|
14484
14662
|
}
|
|
@@ -14486,17 +14664,15 @@ var init_parser = __esm(() => {
|
|
|
14486
14664
|
this.addError("Empty if condition", ifToken.range, "MISSING_EXPRESSION_AFTER_EQUALS" /* MISSING_EXPRESSION_AFTER_EQUALS */);
|
|
14487
14665
|
}
|
|
14488
14666
|
const body = [];
|
|
14667
|
+
let blockEndingTrivia;
|
|
14489
14668
|
if (this.check("LBRACE")) {
|
|
14490
14669
|
const lbrace_index = this.current;
|
|
14491
14670
|
const lbrace_token = this.advance();
|
|
14492
14671
|
const has_condition_before = lbrace_token.range.start.line === condition_start_line;
|
|
14493
14672
|
this.validate_open_brace(lbrace_token, lbrace_index, has_condition_before);
|
|
14494
|
-
|
|
14495
|
-
|
|
14496
|
-
|
|
14497
|
-
body.push(stmt);
|
|
14498
|
-
}
|
|
14499
|
-
}
|
|
14673
|
+
const { body: my_body, blockEndingTrivia: my_block_ending_trivia } = this.parseBraceBody();
|
|
14674
|
+
body.push(...my_body);
|
|
14675
|
+
blockEndingTrivia = my_block_ending_trivia;
|
|
14500
14676
|
if (this.check("RBRACE")) {
|
|
14501
14677
|
const rbrace_index = this.current;
|
|
14502
14678
|
const rbrace_token = this.advance();
|
|
@@ -14509,7 +14685,8 @@ var init_parser = __esm(() => {
|
|
|
14509
14685
|
type: "if",
|
|
14510
14686
|
condition: condition.trim(),
|
|
14511
14687
|
body,
|
|
14512
|
-
range: this.makeRange(ifToken.range.start, this.previous().range.end)
|
|
14688
|
+
range: this.makeRange(ifToken.range.start, this.previous().range.end),
|
|
14689
|
+
blockEndingTrivia
|
|
14513
14690
|
};
|
|
14514
14691
|
}
|
|
14515
14692
|
parseElseStatement() {
|
|
@@ -14523,17 +14700,17 @@ var init_parser = __esm(() => {
|
|
|
14523
14700
|
};
|
|
14524
14701
|
}
|
|
14525
14702
|
const body = [];
|
|
14703
|
+
let blockEndingTrivia;
|
|
14704
|
+
let is_brace_else = false;
|
|
14526
14705
|
if (this.check("LBRACE")) {
|
|
14706
|
+
is_brace_else = true;
|
|
14527
14707
|
const lbrace_index = this.current;
|
|
14528
14708
|
const lbrace_token = this.advance();
|
|
14529
14709
|
const has_condition_before = lbrace_token.range.start.line === elseToken.range.start.line;
|
|
14530
14710
|
this.validate_open_brace(lbrace_token, lbrace_index, has_condition_before);
|
|
14531
|
-
|
|
14532
|
-
|
|
14533
|
-
|
|
14534
|
-
body.push(stmt);
|
|
14535
|
-
}
|
|
14536
|
-
}
|
|
14711
|
+
const { body: my_body, blockEndingTrivia: my_block_ending_trivia } = this.parseBraceBody();
|
|
14712
|
+
body.push(...my_body);
|
|
14713
|
+
blockEndingTrivia = my_block_ending_trivia;
|
|
14537
14714
|
if (this.check("RBRACE")) {
|
|
14538
14715
|
const rbrace_index = this.current;
|
|
14539
14716
|
const rbrace_token = this.advance();
|
|
@@ -14547,10 +14724,12 @@ var init_parser = __esm(() => {
|
|
|
14547
14724
|
body.push(stmt);
|
|
14548
14725
|
}
|
|
14549
14726
|
}
|
|
14727
|
+
const end_position = !is_brace_else && body.length > 0 ? body[body.length - 1].range.end : this.previous().range.end;
|
|
14550
14728
|
return {
|
|
14551
14729
|
type: "else",
|
|
14552
14730
|
body,
|
|
14553
|
-
range: this.makeRange(elseToken.range.start,
|
|
14731
|
+
range: this.makeRange(elseToken.range.start, end_position),
|
|
14732
|
+
blockEndingTrivia
|
|
14554
14733
|
};
|
|
14555
14734
|
}
|
|
14556
14735
|
parseLoopStatement() {
|
|
@@ -14566,9 +14745,9 @@ var init_parser = __esm(() => {
|
|
|
14566
14745
|
const is_foreach_spec = this.check("WORD") && (this.peek().value === "in" || this.peek().value === "of");
|
|
14567
14746
|
if (is_forvalues_spec || is_foreach_spec) {
|
|
14568
14747
|
const specType = this.advance().value;
|
|
14569
|
-
|
|
14570
|
-
|
|
14571
|
-
|
|
14748
|
+
const spec_tokens = [];
|
|
14749
|
+
const preceded_by_continuation = [];
|
|
14750
|
+
const continuation = new ContinuationTracker;
|
|
14572
14751
|
while (!this.check("LBRACE") && !this.isAtEnd()) {
|
|
14573
14752
|
if (this.check("STATEMENT_TERMINATOR")) {
|
|
14574
14753
|
if (is_swallowed_continuation_terminator(this.tokens[this.current], this.current > 0 && this.tokens[this.current - 1].type === "CONTINUATION")) {
|
|
@@ -14579,44 +14758,24 @@ var init_parser = __esm(() => {
|
|
|
14579
14758
|
}
|
|
14580
14759
|
const token = this.advance();
|
|
14581
14760
|
if (token.type === "CONTINUATION") {
|
|
14582
|
-
|
|
14583
|
-
continue;
|
|
14584
|
-
}
|
|
14585
|
-
if (token.type === "WHITESPACE") {
|
|
14761
|
+
continuation.note_continuation(token);
|
|
14586
14762
|
continue;
|
|
14587
14763
|
}
|
|
14588
|
-
|
|
14589
|
-
|
|
14590
|
-
let needs_separator;
|
|
14591
|
-
if (same_line) {
|
|
14592
|
-
needs_separator = token.range.start.character - prev_spec_token.range.end.character > 0;
|
|
14593
|
-
} else if (continuation_pending) {
|
|
14594
|
-
needs_separator = token.range.start.character > 0;
|
|
14595
|
-
} else {
|
|
14596
|
-
needs_separator = true;
|
|
14597
|
-
}
|
|
14598
|
-
if (needs_separator) {
|
|
14599
|
-
loop_spec_body += " ";
|
|
14600
|
-
}
|
|
14601
|
-
}
|
|
14602
|
-
loop_spec_body += token.value;
|
|
14603
|
-
prev_spec_token = token;
|
|
14604
|
-
continuation_pending = false;
|
|
14764
|
+
spec_tokens.push(token);
|
|
14765
|
+
preceded_by_continuation.push(continuation.collect(token));
|
|
14605
14766
|
}
|
|
14606
|
-
loopSpec = specType + " " +
|
|
14767
|
+
loopSpec = specType + " " + this.reconstruct_value_tokens(spec_tokens, preceded_by_continuation).trim();
|
|
14607
14768
|
}
|
|
14608
14769
|
const body = [];
|
|
14770
|
+
let blockEndingTrivia;
|
|
14609
14771
|
if (this.check("LBRACE")) {
|
|
14610
14772
|
const lbrace_index = this.current;
|
|
14611
14773
|
const lbrace_token = this.advance();
|
|
14612
14774
|
const has_condition_before = lbrace_token.range.start.line === loop_start_line;
|
|
14613
14775
|
this.validate_open_brace(lbrace_token, lbrace_index, has_condition_before);
|
|
14614
|
-
|
|
14615
|
-
|
|
14616
|
-
|
|
14617
|
-
body.push(stmt);
|
|
14618
|
-
}
|
|
14619
|
-
}
|
|
14776
|
+
const { body: my_body, blockEndingTrivia: my_block_ending_trivia } = this.parseBraceBody();
|
|
14777
|
+
body.push(...my_body);
|
|
14778
|
+
blockEndingTrivia = my_block_ending_trivia;
|
|
14620
14779
|
if (this.check("RBRACE")) {
|
|
14621
14780
|
const rbrace_index = this.current;
|
|
14622
14781
|
const rbrace_token = this.advance();
|
|
@@ -14630,17 +14789,24 @@ var init_parser = __esm(() => {
|
|
|
14630
14789
|
loopVar,
|
|
14631
14790
|
loopSpec,
|
|
14632
14791
|
body,
|
|
14633
|
-
range: this.makeRange(loopToken.range.start, this.previous().range.end)
|
|
14792
|
+
range: this.makeRange(loopToken.range.start, this.previous().range.end),
|
|
14793
|
+
blockEndingTrivia
|
|
14634
14794
|
};
|
|
14635
14795
|
}
|
|
14636
14796
|
parseWhileStatement() {
|
|
14637
14797
|
const whileToken = this.advance();
|
|
14638
14798
|
const while_start_line = whileToken.range.start.line;
|
|
14639
14799
|
const condition_tokens = [];
|
|
14800
|
+
const preceded_by_continuation = [];
|
|
14801
|
+
const continuation = new ContinuationTracker;
|
|
14640
14802
|
let paren_depth = 0;
|
|
14641
14803
|
while (!this.check("LBRACE") && !this.isAtEnd()) {
|
|
14642
|
-
if (this.
|
|
14643
|
-
|
|
14804
|
+
if (this.check("CONTINUATION")) {
|
|
14805
|
+
const cont_token = this.peek();
|
|
14806
|
+
if (this.skipContinuation()) {
|
|
14807
|
+
continuation.note_continuation(cont_token);
|
|
14808
|
+
continue;
|
|
14809
|
+
}
|
|
14644
14810
|
}
|
|
14645
14811
|
if (this.check("STATEMENT_TERMINATOR")) {
|
|
14646
14812
|
break;
|
|
@@ -14655,11 +14821,10 @@ var init_parser = __esm(() => {
|
|
|
14655
14821
|
paren_depth = 0;
|
|
14656
14822
|
}
|
|
14657
14823
|
}
|
|
14658
|
-
|
|
14659
|
-
|
|
14660
|
-
}
|
|
14824
|
+
condition_tokens.push(token);
|
|
14825
|
+
preceded_by_continuation.push(continuation.collect(token));
|
|
14661
14826
|
}
|
|
14662
|
-
const condition = this.
|
|
14827
|
+
const condition = this.reconstruct_value_tokens(condition_tokens, preceded_by_continuation).trim();
|
|
14663
14828
|
if (paren_depth > 0) {
|
|
14664
14829
|
this.addError("Unbalanced parentheses in while condition: missing closing parenthesis", whileToken.range, "UNBALANCED_PARENTHESES" /* UNBALANCED_PARENTHESES */);
|
|
14665
14830
|
}
|
|
@@ -14667,17 +14832,15 @@ var init_parser = __esm(() => {
|
|
|
14667
14832
|
this.addError("Empty while condition", whileToken.range, "MISSING_EXPRESSION_AFTER_EQUALS" /* MISSING_EXPRESSION_AFTER_EQUALS */);
|
|
14668
14833
|
}
|
|
14669
14834
|
const body = [];
|
|
14835
|
+
let blockEndingTrivia;
|
|
14670
14836
|
if (this.check("LBRACE")) {
|
|
14671
14837
|
const lbrace_index = this.current;
|
|
14672
14838
|
const lbrace_token = this.advance();
|
|
14673
14839
|
const has_condition_before = lbrace_token.range.start.line === while_start_line;
|
|
14674
14840
|
this.validate_open_brace(lbrace_token, lbrace_index, has_condition_before);
|
|
14675
|
-
|
|
14676
|
-
|
|
14677
|
-
|
|
14678
|
-
body.push(stmt);
|
|
14679
|
-
}
|
|
14680
|
-
}
|
|
14841
|
+
const { body: my_body, blockEndingTrivia: my_block_ending_trivia } = this.parseBraceBody();
|
|
14842
|
+
body.push(...my_body);
|
|
14843
|
+
blockEndingTrivia = my_block_ending_trivia;
|
|
14681
14844
|
if (this.check("RBRACE")) {
|
|
14682
14845
|
const rbrace_index = this.current;
|
|
14683
14846
|
const rbrace_token = this.advance();
|
|
@@ -14690,7 +14853,8 @@ var init_parser = __esm(() => {
|
|
|
14690
14853
|
type: "while",
|
|
14691
14854
|
condition: condition.trim(),
|
|
14692
14855
|
body,
|
|
14693
|
-
range: this.makeRange(whileToken.range.start, this.previous().range.end)
|
|
14856
|
+
range: this.makeRange(whileToken.range.start, this.previous().range.end),
|
|
14857
|
+
blockEndingTrivia
|
|
14694
14858
|
};
|
|
14695
14859
|
}
|
|
14696
14860
|
parseStringStatement() {
|
|
@@ -14698,9 +14862,7 @@ var init_parser = __esm(() => {
|
|
|
14698
14862
|
const statement_tokens = [];
|
|
14699
14863
|
while (!this.check("STATEMENT_TERMINATOR") && !this.isAtEnd()) {
|
|
14700
14864
|
const token = this.advance();
|
|
14701
|
-
|
|
14702
|
-
statement_tokens.push(token);
|
|
14703
|
-
}
|
|
14865
|
+
statement_tokens.push(token);
|
|
14704
14866
|
}
|
|
14705
14867
|
const content = this.reconstructTokensWithSpacing(statement_tokens);
|
|
14706
14868
|
return {
|
|
@@ -14711,15 +14873,15 @@ var init_parser = __esm(() => {
|
|
|
14711
14873
|
};
|
|
14712
14874
|
}
|
|
14713
14875
|
parseFrameBlock() {
|
|
14876
|
+
const frame_index = this.current;
|
|
14714
14877
|
const frame_token = this.advance();
|
|
14715
14878
|
const frame_start_line = frame_token.range.start.line;
|
|
14716
14879
|
this.skipTrivia();
|
|
14717
14880
|
if (!this.check("WORD")) {
|
|
14718
|
-
this.current
|
|
14881
|
+
this.current = frame_index;
|
|
14719
14882
|
return null;
|
|
14720
14883
|
}
|
|
14721
14884
|
const name_token = this.peek();
|
|
14722
|
-
const saved_position = this.current;
|
|
14723
14885
|
this.advance();
|
|
14724
14886
|
this.skipTrivia();
|
|
14725
14887
|
if (this.check("COLON")) {
|
|
@@ -14735,7 +14897,7 @@ var init_parser = __esm(() => {
|
|
|
14735
14897
|
return this.parseFramePrefixedCommand(frame_prefix, [], frame_token);
|
|
14736
14898
|
}
|
|
14737
14899
|
if (!this.check("LBRACE")) {
|
|
14738
|
-
this.current =
|
|
14900
|
+
this.current = frame_index;
|
|
14739
14901
|
return null;
|
|
14740
14902
|
}
|
|
14741
14903
|
const frame_name = name_token.value;
|
|
@@ -14743,13 +14905,7 @@ var init_parser = __esm(() => {
|
|
|
14743
14905
|
const lbrace_token = this.advance();
|
|
14744
14906
|
const has_condition_before = lbrace_token.range.start.line === frame_start_line;
|
|
14745
14907
|
this.validate_open_brace(lbrace_token, lbrace_index, has_condition_before);
|
|
14746
|
-
const body =
|
|
14747
|
-
while (!this.check("RBRACE") && !this.isAtEnd()) {
|
|
14748
|
-
const stmt = this.parseStatement();
|
|
14749
|
-
if (stmt) {
|
|
14750
|
-
body.push(stmt);
|
|
14751
|
-
}
|
|
14752
|
-
}
|
|
14908
|
+
const { body, blockEndingTrivia } = this.parseBraceBody();
|
|
14753
14909
|
if (this.check("RBRACE")) {
|
|
14754
14910
|
const rbrace_index = this.current;
|
|
14755
14911
|
const rbrace_token = this.advance();
|
|
@@ -14761,7 +14917,8 @@ var init_parser = __esm(() => {
|
|
|
14761
14917
|
type: "frame",
|
|
14762
14918
|
frameName: frame_name,
|
|
14763
14919
|
body,
|
|
14764
|
-
range: this.makeRange(frame_token.range.start, this.previous().range.end)
|
|
14920
|
+
range: this.makeRange(frame_token.range.start, this.previous().range.end),
|
|
14921
|
+
blockEndingTrivia
|
|
14765
14922
|
};
|
|
14766
14923
|
}
|
|
14767
14924
|
parseUnabCommandBody(command_token) {
|
|
@@ -14822,6 +14979,9 @@ var init_parser = __esm(() => {
|
|
|
14822
14979
|
const parsed = this.parse_option_argument_inside_parens();
|
|
14823
14980
|
option.argument = parsed.argument;
|
|
14824
14981
|
option.argument_range = parsed.argument_range;
|
|
14982
|
+
if (parsed.argument_unclosed) {
|
|
14983
|
+
option.argument_unclosed = true;
|
|
14984
|
+
}
|
|
14825
14985
|
}
|
|
14826
14986
|
options.push(option);
|
|
14827
14987
|
} else {
|
|
@@ -14848,7 +15008,7 @@ var init_parser = __esm(() => {
|
|
|
14848
15008
|
}
|
|
14849
15009
|
collectTrivia() {
|
|
14850
15010
|
const trivia = [];
|
|
14851
|
-
while (this.check("COMMENT_LINE") || this.check("COMMENT_BLOCK") || this.check("CONTINUATION")
|
|
15011
|
+
while (this.check("COMMENT_LINE") || this.check("COMMENT_BLOCK") || this.check("CONTINUATION")) {
|
|
14852
15012
|
const token = this.advance();
|
|
14853
15013
|
if (token.type === "COMMENT_LINE") {
|
|
14854
15014
|
const style = token.value.startsWith("*") ? "star" : "slash";
|
|
@@ -14881,12 +15041,42 @@ var init_parser = __esm(() => {
|
|
|
14881
15041
|
this.advance();
|
|
14882
15042
|
}
|
|
14883
15043
|
}
|
|
15044
|
+
parseBraceBody() {
|
|
15045
|
+
const body = [];
|
|
15046
|
+
while (!this.isAtEnd()) {
|
|
15047
|
+
const my_trivia = this.collectTrivia();
|
|
15048
|
+
if (my_trivia.length > 0) {
|
|
15049
|
+
this.pending_trivia.push(...my_trivia);
|
|
15050
|
+
}
|
|
15051
|
+
if (this.check("RBRACE") || this.isAtEnd()) {
|
|
15052
|
+
break;
|
|
15053
|
+
}
|
|
15054
|
+
const stmt = this.parseStatement();
|
|
15055
|
+
if (stmt) {
|
|
15056
|
+
body.push(stmt);
|
|
15057
|
+
}
|
|
15058
|
+
}
|
|
15059
|
+
const blockEndingTrivia = this.check("RBRACE") ? this.drainBlockEndingTrivia() : undefined;
|
|
15060
|
+
return { body, blockEndingTrivia };
|
|
15061
|
+
}
|
|
15062
|
+
drainBlockEndingTrivia() {
|
|
15063
|
+
if (this.pending_trivia.length === 0) {
|
|
15064
|
+
return;
|
|
15065
|
+
}
|
|
15066
|
+
const has_continuation = this.pending_trivia.some((my_trivia) => my_trivia.type === "comment" && my_trivia.style === "continuation");
|
|
15067
|
+
if (has_continuation) {
|
|
15068
|
+
return;
|
|
15069
|
+
}
|
|
15070
|
+
const block_ending_trivia = this.pending_trivia;
|
|
15071
|
+
this.pending_trivia = [];
|
|
15072
|
+
return block_ending_trivia;
|
|
15073
|
+
}
|
|
14884
15074
|
skipMacroDefinitionTrivia() {
|
|
14885
15075
|
while (!this.isAtEnd()) {
|
|
14886
15076
|
if (this.skipContinuation()) {
|
|
14887
15077
|
continue;
|
|
14888
15078
|
}
|
|
14889
|
-
if (this.check("
|
|
15079
|
+
if (this.check("COMMENT_LINE") || this.check("COMMENT_BLOCK")) {
|
|
14890
15080
|
this.advance();
|
|
14891
15081
|
continue;
|
|
14892
15082
|
}
|
|
@@ -14903,7 +15093,7 @@ var init_parser = __esm(() => {
|
|
|
14903
15093
|
}
|
|
14904
15094
|
continue;
|
|
14905
15095
|
}
|
|
14906
|
-
if (token.type === "COMMENT_LINE" || token.type === "COMMENT_BLOCK"
|
|
15096
|
+
if (token.type === "COMMENT_LINE" || token.type === "COMMENT_BLOCK") {
|
|
14907
15097
|
offset++;
|
|
14908
15098
|
continue;
|
|
14909
15099
|
}
|
|
@@ -14985,11 +15175,6 @@ var init_parser = __esm(() => {
|
|
|
14985
15175
|
peek() {
|
|
14986
15176
|
return this.tokens[this.current];
|
|
14987
15177
|
}
|
|
14988
|
-
peekNext() {
|
|
14989
|
-
if (this.current + 1 >= this.tokens.length)
|
|
14990
|
-
return;
|
|
14991
|
-
return this.tokens[this.current + 1];
|
|
14992
|
-
}
|
|
14993
15178
|
previous() {
|
|
14994
15179
|
return this.tokens[this.current - 1];
|
|
14995
15180
|
}
|
|
@@ -15007,12 +15192,18 @@ var init_parser = __esm(() => {
|
|
|
15007
15192
|
return this.context_tracker;
|
|
15008
15193
|
}
|
|
15009
15194
|
parseExpression() {
|
|
15010
|
-
|
|
15195
|
+
const the_tokens = [];
|
|
15196
|
+
const preceded_by_continuation = [];
|
|
15197
|
+
const continuation = new ContinuationTracker;
|
|
15011
15198
|
let paren_depth = 0;
|
|
15012
15199
|
const start_pos = this.current;
|
|
15013
15200
|
while (!this.isAtEnd()) {
|
|
15014
15201
|
const token = this.peek();
|
|
15202
|
+
if (token.type === "STATEMENT_TERMINATOR") {
|
|
15203
|
+
break;
|
|
15204
|
+
}
|
|
15015
15205
|
if (this.skipContinuation()) {
|
|
15206
|
+
continuation.note_continuation(token);
|
|
15016
15207
|
continue;
|
|
15017
15208
|
}
|
|
15018
15209
|
if (token.type === "LPAREN") {
|
|
@@ -15025,7 +15216,7 @@ var init_parser = __esm(() => {
|
|
|
15025
15216
|
}
|
|
15026
15217
|
}
|
|
15027
15218
|
if (paren_depth === 0) {
|
|
15028
|
-
if (token.type === "COMMA"
|
|
15219
|
+
if (token.type === "COMMA") {
|
|
15029
15220
|
break;
|
|
15030
15221
|
}
|
|
15031
15222
|
if (token.type === "WORD" && (token.value === "if" || token.value === "in")) {
|
|
@@ -15035,13 +15226,11 @@ var init_parser = __esm(() => {
|
|
|
15035
15226
|
if (token.type === "COMMENT_LINE" || token.type === "COMMENT_BLOCK") {
|
|
15036
15227
|
break;
|
|
15037
15228
|
}
|
|
15038
|
-
|
|
15039
|
-
|
|
15040
|
-
|
|
15041
|
-
} else {
|
|
15042
|
-
expression += tokenValue;
|
|
15043
|
-
}
|
|
15229
|
+
this.advance();
|
|
15230
|
+
the_tokens.push(token);
|
|
15231
|
+
preceded_by_continuation.push(continuation.collect(token));
|
|
15044
15232
|
}
|
|
15233
|
+
const expression = this.reconstruct_value_tokens(the_tokens, preceded_by_continuation);
|
|
15045
15234
|
if (paren_depth > 0) {
|
|
15046
15235
|
const end_pos = this.current > 0 ? this.previous().range : this.peek().range;
|
|
15047
15236
|
this.addError("Unbalanced parentheses: missing closing parenthesis", end_pos, "UNBALANCED_PARENTHESES" /* UNBALANCED_PARENTHESES */);
|
|
@@ -15073,7 +15262,9 @@ var init_parser = __esm(() => {
|
|
|
15073
15262
|
return false;
|
|
15074
15263
|
}
|
|
15075
15264
|
parseQualifierExpressionWithStrayDetection(qualifier_type, stop_at_in, check_empty) {
|
|
15076
|
-
|
|
15265
|
+
const the_tokens = [];
|
|
15266
|
+
const preceded_by_continuation = [];
|
|
15267
|
+
const continuation = new ContinuationTracker;
|
|
15077
15268
|
let paren_depth = 0;
|
|
15078
15269
|
let bracket_depth = 0;
|
|
15079
15270
|
const start_token = this.peek();
|
|
@@ -15082,6 +15273,9 @@ var init_parser = __esm(() => {
|
|
|
15082
15273
|
let in_string_context = false;
|
|
15083
15274
|
while (!this.isAtEnd()) {
|
|
15084
15275
|
const token = this.peek();
|
|
15276
|
+
if (token.type === "STATEMENT_TERMINATOR") {
|
|
15277
|
+
break;
|
|
15278
|
+
}
|
|
15085
15279
|
if (token.type === "LPAREN") {
|
|
15086
15280
|
paren_depth++;
|
|
15087
15281
|
state_stack.push("INITIAL");
|
|
@@ -15112,10 +15306,11 @@ var init_parser = __esm(() => {
|
|
|
15112
15306
|
}
|
|
15113
15307
|
}
|
|
15114
15308
|
if (this.skipContinuation()) {
|
|
15309
|
+
continuation.note_continuation(token);
|
|
15115
15310
|
continue;
|
|
15116
15311
|
}
|
|
15117
15312
|
if (paren_depth === 0 && bracket_depth === 0) {
|
|
15118
|
-
if (token.type === "
|
|
15313
|
+
if (token.type === "COMMA") {
|
|
15119
15314
|
break;
|
|
15120
15315
|
}
|
|
15121
15316
|
if (stop_at_in && token.type === "WORD" && token.value === "in") {
|
|
@@ -15138,7 +15333,7 @@ var init_parser = __esm(() => {
|
|
|
15138
15333
|
this.addError(`Unexpected token '${token.value}' after comparison expression. Did you mean to use '&' or '|'?`, token.range, "STRAY_TOKEN_IN_CONDITION" /* STRAY_TOKEN_IN_CONDITION */);
|
|
15139
15334
|
}
|
|
15140
15335
|
}
|
|
15141
|
-
if (token.type !== "
|
|
15336
|
+
if (token.type !== "LPAREN" && token.type !== "RPAREN" && bracket_depth === 0) {
|
|
15142
15337
|
const current_state_for_transition = state_stack[state_stack.length - 1];
|
|
15143
15338
|
if (token.type === "OPERATOR") {
|
|
15144
15339
|
if (token.value === "=" && prev_token && prev_token.type === "OPERATOR" && prev_token.value === "~") {
|
|
@@ -15166,17 +15361,14 @@ var init_parser = __esm(() => {
|
|
|
15166
15361
|
}
|
|
15167
15362
|
prev_token = token;
|
|
15168
15363
|
}
|
|
15169
|
-
|
|
15170
|
-
|
|
15171
|
-
|
|
15172
|
-
} else {
|
|
15173
|
-
expression += tokenValue;
|
|
15174
|
-
}
|
|
15364
|
+
this.advance();
|
|
15365
|
+
the_tokens.push(token);
|
|
15366
|
+
preceded_by_continuation.push(continuation.collect(token));
|
|
15175
15367
|
}
|
|
15176
15368
|
if (paren_depth > 0) {
|
|
15177
15369
|
this.addError(`Unbalanced parentheses in ${qualifier_type} qualifier: missing closing parenthesis`, start_token.range, "UNBALANCED_PARENTHESES" /* UNBALANCED_PARENTHESES */);
|
|
15178
15370
|
}
|
|
15179
|
-
const trimmed_expression =
|
|
15371
|
+
const trimmed_expression = this.reconstruct_value_tokens(the_tokens, preceded_by_continuation).trim();
|
|
15180
15372
|
if (check_empty && trimmed_expression === "") {
|
|
15181
15373
|
this.addError(`Empty ${qualifier_type} qualifier expression`, start_token.range, "MISSING_EXPRESSION_AFTER_EQUALS" /* MISSING_EXPRESSION_AFTER_EQUALS */);
|
|
15182
15374
|
}
|
|
@@ -15219,7 +15411,6 @@ var init_parser = __esm(() => {
|
|
|
15219
15411
|
}
|
|
15220
15412
|
scan_code_on_same_line(start_pos, line) {
|
|
15221
15413
|
const trivia_types = [
|
|
15222
|
-
"WHITESPACE",
|
|
15223
15414
|
"COMMENT_LINE",
|
|
15224
15415
|
"COMMENT_BLOCK",
|
|
15225
15416
|
"CONTINUATION"
|
|
@@ -15258,7 +15449,6 @@ var init_parser = __esm(() => {
|
|
|
15258
15449
|
}
|
|
15259
15450
|
find_code_before_on_same_line(end_pos, line) {
|
|
15260
15451
|
const trivia_types = [
|
|
15261
|
-
"WHITESPACE",
|
|
15262
15452
|
"COMMENT_LINE",
|
|
15263
15453
|
"COMMENT_BLOCK",
|
|
15264
15454
|
"CONTINUATION"
|
|
@@ -15378,12 +15568,12 @@ var init_parser = __esm(() => {
|
|
|
15378
15568
|
if (gap > 0) {
|
|
15379
15569
|
the_parts.push(" ".repeat(gap));
|
|
15380
15570
|
}
|
|
15381
|
-
} else {
|
|
15382
|
-
const
|
|
15383
|
-
|
|
15384
|
-
|
|
15385
|
-
|
|
15386
|
-
the_parts.push(" ");
|
|
15571
|
+
} else if (my_token.range.start.line > prev_token.range.end.line) {
|
|
15572
|
+
const line_gap = my_token.range.start.line - prev_token.range.end.line;
|
|
15573
|
+
the_parts.push(`
|
|
15574
|
+
`.repeat(line_gap));
|
|
15575
|
+
if (my_token.range.start.character > 0) {
|
|
15576
|
+
the_parts.push(" ".repeat(my_token.range.start.character));
|
|
15387
15577
|
}
|
|
15388
15578
|
}
|
|
15389
15579
|
}
|
|
@@ -16551,10 +16741,6 @@ function parse_macro_def_head(statement_tokens) {
|
|
|
16551
16741
|
const run = [];
|
|
16552
16742
|
while (i < statement_tokens.length) {
|
|
16553
16743
|
const my_tok = statement_tokens[i];
|
|
16554
|
-
if (my_tok.type === "WHITESPACE") {
|
|
16555
|
-
i++;
|
|
16556
|
-
continue;
|
|
16557
|
-
}
|
|
16558
16744
|
if (!NAME_TOKEN_TYPES.has(my_tok.type))
|
|
16559
16745
|
break;
|
|
16560
16746
|
if (run.length > 0 && !tokens_adjacent(run[run.length - 1], my_tok))
|
|
@@ -17046,6 +17232,57 @@ var init_macro_creating_commands = __esm(() => {
|
|
|
17046
17232
|
];
|
|
17047
17233
|
});
|
|
17048
17234
|
|
|
17235
|
+
// src/utils/token-utils.ts
|
|
17236
|
+
function position_before2(a, b) {
|
|
17237
|
+
return a.line < b.line || a.line === b.line && a.character < b.character;
|
|
17238
|
+
}
|
|
17239
|
+
function position_at_or_before(a, b) {
|
|
17240
|
+
return a.line < b.line || a.line === b.line && a.character <= b.character;
|
|
17241
|
+
}
|
|
17242
|
+
function find_last_token_starting_at_or_before(tokens, position) {
|
|
17243
|
+
let low = 0;
|
|
17244
|
+
let high = tokens.length - 1;
|
|
17245
|
+
let best = -1;
|
|
17246
|
+
while (low <= high) {
|
|
17247
|
+
const mid = low + high >>> 1;
|
|
17248
|
+
const start = tokens[mid].range.start;
|
|
17249
|
+
if (position_at_or_before(start, position)) {
|
|
17250
|
+
best = mid;
|
|
17251
|
+
low = mid + 1;
|
|
17252
|
+
} else {
|
|
17253
|
+
high = mid - 1;
|
|
17254
|
+
}
|
|
17255
|
+
}
|
|
17256
|
+
return best;
|
|
17257
|
+
}
|
|
17258
|
+
function find_last_token_starting_before(tokens, position) {
|
|
17259
|
+
let low = 0;
|
|
17260
|
+
let high = tokens.length - 1;
|
|
17261
|
+
let best = -1;
|
|
17262
|
+
while (low <= high) {
|
|
17263
|
+
const mid = low + high >>> 1;
|
|
17264
|
+
const start = tokens[mid].range.start;
|
|
17265
|
+
if (position_before2(start, position)) {
|
|
17266
|
+
best = mid;
|
|
17267
|
+
low = mid + 1;
|
|
17268
|
+
} else {
|
|
17269
|
+
high = mid - 1;
|
|
17270
|
+
}
|
|
17271
|
+
}
|
|
17272
|
+
return best;
|
|
17273
|
+
}
|
|
17274
|
+
function find_token_index_at_position(tokens, position) {
|
|
17275
|
+
const candidate = find_last_token_starting_at_or_before(tokens, position);
|
|
17276
|
+
if (candidate === -1) {
|
|
17277
|
+
return -1;
|
|
17278
|
+
}
|
|
17279
|
+
const end = tokens[candidate].range.end;
|
|
17280
|
+
if (position_before2(position, end)) {
|
|
17281
|
+
return candidate;
|
|
17282
|
+
}
|
|
17283
|
+
return -1;
|
|
17284
|
+
}
|
|
17285
|
+
|
|
17049
17286
|
// src/utils/statement-span.ts
|
|
17050
17287
|
function next_statement_line_span(tokens, from_index) {
|
|
17051
17288
|
let my_first_index = from_index + 1;
|
|
@@ -17086,13 +17323,101 @@ function next_statement_line_span(tokens, from_index) {
|
|
|
17086
17323
|
}
|
|
17087
17324
|
return { start_line, end_line };
|
|
17088
17325
|
}
|
|
17089
|
-
|
|
17326
|
+
function inline_embedded_statement_end(tokens, opener_index) {
|
|
17327
|
+
let my_last_content_index = opener_index;
|
|
17328
|
+
let my_i = opener_index + 1;
|
|
17329
|
+
while (my_i < tokens.length && tokens[my_i].type !== "STATEMENT_TERMINATOR" && tokens[my_i].type !== "EOF") {
|
|
17330
|
+
my_last_content_index = my_i;
|
|
17331
|
+
my_i++;
|
|
17332
|
+
}
|
|
17333
|
+
const end_line = tokens[my_last_content_index].range.end.line;
|
|
17334
|
+
const end_index = my_i < tokens.length && tokens[my_i].type === "STATEMENT_TERMINATOR" ? my_i : my_last_content_index;
|
|
17335
|
+
return { end_index, end_line };
|
|
17336
|
+
}
|
|
17337
|
+
function logical_statement_start(tokens, position, min_line = 0) {
|
|
17338
|
+
if (tokens === undefined || tokens.length === 0) {
|
|
17339
|
+
return;
|
|
17340
|
+
}
|
|
17341
|
+
let search_index = find_last_token_starting_before(tokens, position);
|
|
17342
|
+
while (search_index >= 0 && tokens[search_index].type === "EOF") {
|
|
17343
|
+
search_index--;
|
|
17344
|
+
}
|
|
17345
|
+
if (search_index < 0) {
|
|
17346
|
+
return;
|
|
17347
|
+
}
|
|
17348
|
+
let boundary_index = -1;
|
|
17349
|
+
let my_steps = 0;
|
|
17350
|
+
for (let my_i = search_index;my_i >= 0; my_i--) {
|
|
17351
|
+
if (++my_steps > MAX_STATEMENT_TOKENS) {
|
|
17352
|
+
return;
|
|
17353
|
+
}
|
|
17354
|
+
const my_token = tokens[my_i];
|
|
17355
|
+
if (my_token.range.start.line < min_line) {
|
|
17356
|
+
break;
|
|
17357
|
+
}
|
|
17358
|
+
if (is_swallowed_continuation_terminator(my_token, my_i > 0 && tokens[my_i - 1].type === "CONTINUATION")) {
|
|
17359
|
+
continue;
|
|
17360
|
+
}
|
|
17361
|
+
if (LOGICAL_BOUNDARY_TYPES.has(my_token.type)) {
|
|
17362
|
+
boundary_index = my_i;
|
|
17363
|
+
break;
|
|
17364
|
+
}
|
|
17365
|
+
}
|
|
17366
|
+
let boundary_opens_embedded_body = false;
|
|
17367
|
+
if (boundary_index >= 0) {
|
|
17368
|
+
const my_boundary_type = tokens[boundary_index].type;
|
|
17369
|
+
if (my_boundary_type === "MATA_START" || my_boundary_type === "PYTHON_START") {
|
|
17370
|
+
boundary_opens_embedded_body = true;
|
|
17371
|
+
} else if (my_boundary_type === "LBRACE") {
|
|
17372
|
+
for (let my_j = boundary_index - 1;my_j >= 0; my_j--) {
|
|
17373
|
+
const my_prev_type = tokens[my_j].type;
|
|
17374
|
+
if (CONTINUATION_NEUTRAL_TYPES.has(my_prev_type) || my_prev_type === "WHITESPACE") {
|
|
17375
|
+
continue;
|
|
17376
|
+
}
|
|
17377
|
+
boundary_opens_embedded_body = my_prev_type === "MATA_START" || my_prev_type === "PYTHON_START";
|
|
17378
|
+
break;
|
|
17379
|
+
}
|
|
17380
|
+
}
|
|
17381
|
+
}
|
|
17382
|
+
let first_index = -1;
|
|
17383
|
+
for (let my_i = boundary_index + 1;my_i < tokens.length; my_i++) {
|
|
17384
|
+
const my_token = tokens[my_i];
|
|
17385
|
+
if (my_token.type === "EOF") {
|
|
17386
|
+
break;
|
|
17387
|
+
}
|
|
17388
|
+
if (my_token.range.start.line < min_line) {
|
|
17389
|
+
continue;
|
|
17390
|
+
}
|
|
17391
|
+
if (!STATEMENT_LEADING_TRIVIA_TYPES.has(my_token.type)) {
|
|
17392
|
+
first_index = my_i;
|
|
17393
|
+
break;
|
|
17394
|
+
}
|
|
17395
|
+
}
|
|
17396
|
+
if (first_index !== -1 && !boundary_opens_embedded_body) {
|
|
17397
|
+
const my_start = tokens[first_index].range.start;
|
|
17398
|
+
const at_or_before_cursor = my_start.line < position.line || my_start.line === position.line && my_start.character <= position.character;
|
|
17399
|
+
if (at_or_before_cursor) {
|
|
17400
|
+
return {
|
|
17401
|
+
index: first_index,
|
|
17402
|
+
line: my_start.line,
|
|
17403
|
+
character: my_start.character
|
|
17404
|
+
};
|
|
17405
|
+
}
|
|
17406
|
+
}
|
|
17407
|
+
const resume_character = boundary_index >= 0 && tokens[boundary_index].range.end.line === position.line ? Math.min(tokens[boundary_index].range.end.character, position.character) : 0;
|
|
17408
|
+
return {
|
|
17409
|
+
index: first_index >= 0 ? first_index : boundary_index + 1,
|
|
17410
|
+
line: position.line,
|
|
17411
|
+
character: resume_character
|
|
17412
|
+
};
|
|
17413
|
+
}
|
|
17414
|
+
var LEADING_TRIVIA_TYPES, BODY_OPENER_TYPES, CONTINUATION_NEUTRAL_TYPES, LOGICAL_BOUNDARY_TYPES, STATEMENT_LEADING_TRIVIA_TYPES, MAX_STATEMENT_TOKENS = 4096;
|
|
17090
17415
|
var init_statement_span = __esm(() => {
|
|
17091
17416
|
LEADING_TRIVIA_TYPES = new Set([
|
|
17092
|
-
"WHITESPACE",
|
|
17093
17417
|
"COMMENT_LINE",
|
|
17094
17418
|
"COMMENT_BLOCK",
|
|
17095
17419
|
"CONTINUATION",
|
|
17420
|
+
"WHITESPACE",
|
|
17096
17421
|
"STATEMENT_TERMINATOR",
|
|
17097
17422
|
"DELIMIT_DIRECTIVE"
|
|
17098
17423
|
]);
|
|
@@ -17102,10 +17427,26 @@ var init_statement_span = __esm(() => {
|
|
|
17102
17427
|
"PYTHON_START"
|
|
17103
17428
|
]);
|
|
17104
17429
|
CONTINUATION_NEUTRAL_TYPES = new Set([
|
|
17105
|
-
"WHITESPACE",
|
|
17106
17430
|
"COMMENT_LINE",
|
|
17107
17431
|
"COMMENT_BLOCK"
|
|
17108
17432
|
]);
|
|
17433
|
+
LOGICAL_BOUNDARY_TYPES = new Set([
|
|
17434
|
+
"STATEMENT_TERMINATOR",
|
|
17435
|
+
"LBRACE",
|
|
17436
|
+
"RBRACE",
|
|
17437
|
+
"DELIMIT_DIRECTIVE",
|
|
17438
|
+
"MATA_START",
|
|
17439
|
+
"PYTHON_START",
|
|
17440
|
+
"END_MATA",
|
|
17441
|
+
"END_PYTHON"
|
|
17442
|
+
]);
|
|
17443
|
+
STATEMENT_LEADING_TRIVIA_TYPES = new Set([
|
|
17444
|
+
"COMMENT_LINE",
|
|
17445
|
+
"COMMENT_BLOCK",
|
|
17446
|
+
"CONTINUATION",
|
|
17447
|
+
"WHITESPACE",
|
|
17448
|
+
"STATEMENT_TERMINATOR"
|
|
17449
|
+
]);
|
|
17109
17450
|
});
|
|
17110
17451
|
|
|
17111
17452
|
// src/analyzer/index.ts
|
|
@@ -17212,9 +17553,7 @@ class SemanticAnalyzer {
|
|
|
17212
17553
|
};
|
|
17213
17554
|
}
|
|
17214
17555
|
extract_comment_directives(ast) {
|
|
17215
|
-
|
|
17216
|
-
this.extract_directives_from_node(node);
|
|
17217
|
-
}
|
|
17556
|
+
this.extract_directives_from_nodes(ast.nodes);
|
|
17218
17557
|
}
|
|
17219
17558
|
extract_comment_directives_from_tokens(tokens, symbols, dofile_scope) {
|
|
17220
17559
|
this.parse_declaration_directives_from_tokens(tokens, symbols, dofile_scope);
|
|
@@ -17348,25 +17687,45 @@ class SemanticAnalyzer {
|
|
|
17348
17687
|
break;
|
|
17349
17688
|
}
|
|
17350
17689
|
}
|
|
17351
|
-
|
|
17352
|
-
|
|
17353
|
-
|
|
17354
|
-
|
|
17690
|
+
extract_directives_from_nodes(nodes, outer_successor) {
|
|
17691
|
+
for (let my_index = 0;my_index < nodes.length; my_index++) {
|
|
17692
|
+
const node = nodes[my_index];
|
|
17693
|
+
if (this.has_trivia(node) && node.leadingTrivia) {
|
|
17694
|
+
for (const trivia of node.leadingTrivia) {
|
|
17695
|
+
this.parse_directive(trivia, node);
|
|
17696
|
+
}
|
|
17355
17697
|
}
|
|
17356
|
-
|
|
17357
|
-
|
|
17358
|
-
|
|
17359
|
-
|
|
17698
|
+
const following_node = nodes[my_index + 1] ?? outer_successor;
|
|
17699
|
+
const node_with_block_ending_trivia = node;
|
|
17700
|
+
if (node_with_block_ending_trivia.blockEndingTrivia) {
|
|
17701
|
+
for (const trivia of node_with_block_ending_trivia.blockEndingTrivia) {
|
|
17702
|
+
this.parse_directive(trivia, following_node);
|
|
17703
|
+
}
|
|
17360
17704
|
}
|
|
17361
|
-
|
|
17362
|
-
|
|
17363
|
-
this.
|
|
17705
|
+
const the_child_body = this.directive_recursion_body(node);
|
|
17706
|
+
if (the_child_body) {
|
|
17707
|
+
this.extract_directives_from_nodes(the_child_body, following_node);
|
|
17364
17708
|
}
|
|
17365
17709
|
}
|
|
17366
17710
|
}
|
|
17711
|
+
directive_recursion_body(node) {
|
|
17712
|
+
if (node.type === "program") {
|
|
17713
|
+
return node.body;
|
|
17714
|
+
}
|
|
17715
|
+
if (node.type === "frame") {
|
|
17716
|
+
return node.body;
|
|
17717
|
+
}
|
|
17718
|
+
if (this.is_control_flow(node)) {
|
|
17719
|
+
return node.body;
|
|
17720
|
+
}
|
|
17721
|
+
if (node.type === "command" && node.body) {
|
|
17722
|
+
return node.body;
|
|
17723
|
+
}
|
|
17724
|
+
return;
|
|
17725
|
+
}
|
|
17367
17726
|
parse_directive(trivia, following_node) {
|
|
17368
17727
|
const content = trivia.content.trim();
|
|
17369
|
-
if (has_ignore_directive(content) || has_ignore_next_directive(content)) {
|
|
17728
|
+
if (following_node && (has_ignore_directive(content) || has_ignore_next_directive(content))) {
|
|
17370
17729
|
const line_to_ignore = following_node.range.start.line;
|
|
17371
17730
|
this.config.ignored_lines.add(line_to_ignore);
|
|
17372
17731
|
}
|
|
@@ -17386,9 +17745,10 @@ class SemanticAnalyzer {
|
|
|
17386
17745
|
if (token.range.start.line !== line) {
|
|
17387
17746
|
break;
|
|
17388
17747
|
}
|
|
17389
|
-
if (token.type
|
|
17390
|
-
|
|
17748
|
+
if (token.type === "WHITESPACE") {
|
|
17749
|
+
continue;
|
|
17391
17750
|
}
|
|
17751
|
+
return false;
|
|
17392
17752
|
}
|
|
17393
17753
|
return true;
|
|
17394
17754
|
}
|
|
@@ -17508,12 +17868,16 @@ class SemanticAnalyzer {
|
|
|
17508
17868
|
}
|
|
17509
17869
|
}
|
|
17510
17870
|
}
|
|
17871
|
+
semantic_varlist(node) {
|
|
17872
|
+
return (node.varlist ?? []).filter((item) => item.recovery_only !== true);
|
|
17873
|
+
}
|
|
17511
17874
|
extract_c_locals(nodes) {
|
|
17512
17875
|
const c_locals = [];
|
|
17513
17876
|
for (const node of nodes) {
|
|
17514
17877
|
if (node.type === "command") {
|
|
17515
|
-
|
|
17516
|
-
|
|
17878
|
+
const varlist = this.semantic_varlist(node);
|
|
17879
|
+
if (node.fullName === "c_local" && varlist.length > 0) {
|
|
17880
|
+
const name = varlist[0].name;
|
|
17517
17881
|
if (is_valid_identifier(name)) {
|
|
17518
17882
|
c_locals.push(name);
|
|
17519
17883
|
}
|
|
@@ -17544,8 +17908,9 @@ class SemanticAnalyzer {
|
|
|
17544
17908
|
const global_set = new Set;
|
|
17545
17909
|
for (const node of nodes) {
|
|
17546
17910
|
if (node.type === "command") {
|
|
17547
|
-
|
|
17548
|
-
|
|
17911
|
+
const varlist = this.semantic_varlist(node);
|
|
17912
|
+
if (node.fullName === "c_local" && varlist.length > 0) {
|
|
17913
|
+
const macro_name = varlist[0].name;
|
|
17549
17914
|
if (macro_name.startsWith("`") && macro_name.endsWith("'")) {
|
|
17550
17915
|
const inner_name = macro_name.slice(1, -1);
|
|
17551
17916
|
const local_name = inner_name.toLowerCase();
|
|
@@ -17553,8 +17918,8 @@ class SemanticAnalyzer {
|
|
|
17553
17918
|
local_set.add(local_name);
|
|
17554
17919
|
}
|
|
17555
17920
|
}
|
|
17556
|
-
} else if (node.fullName === "global" &&
|
|
17557
|
-
const macro_name =
|
|
17921
|
+
} else if (node.fullName === "global" && varlist.length > 0) {
|
|
17922
|
+
const macro_name = varlist[0].name;
|
|
17558
17923
|
if (macro_name.startsWith("`") && macro_name.endsWith("'")) {
|
|
17559
17924
|
const inner_name = macro_name.slice(1, -1);
|
|
17560
17925
|
const global_name = inner_name.toLowerCase();
|
|
@@ -17763,12 +18128,13 @@ class SemanticAnalyzer {
|
|
|
17763
18128
|
};
|
|
17764
18129
|
}
|
|
17765
18130
|
extract_command_path(node) {
|
|
17766
|
-
|
|
18131
|
+
const varlist = this.semantic_varlist(node);
|
|
18132
|
+
if (varlist.length === 0) {
|
|
17767
18133
|
return null;
|
|
17768
18134
|
}
|
|
17769
18135
|
let raw_path = "";
|
|
17770
18136
|
let has_macro = false;
|
|
17771
|
-
const first_item =
|
|
18137
|
+
const first_item = varlist[0];
|
|
17772
18138
|
const first_name = first_item.name;
|
|
17773
18139
|
const is_complete_double_quoted = first_name.startsWith('"') && first_name.endsWith('"') && first_name.length > 1;
|
|
17774
18140
|
const is_complete_single_quoted = first_name.startsWith("'") && first_name.endsWith("'") && first_name.length > 1;
|
|
@@ -17779,8 +18145,8 @@ class SemanticAnalyzer {
|
|
|
17779
18145
|
const quote_char = first_name[0];
|
|
17780
18146
|
raw_path = first_name;
|
|
17781
18147
|
has_macro = raw_path.includes("`") || raw_path.includes("$");
|
|
17782
|
-
for (let i = 1;i <
|
|
17783
|
-
const item_name =
|
|
18148
|
+
for (let i = 1;i < varlist.length; i++) {
|
|
18149
|
+
const item_name = varlist[i].name;
|
|
17784
18150
|
raw_path += item_name;
|
|
17785
18151
|
if (item_name.includes("`") || item_name.includes("$")) {
|
|
17786
18152
|
has_macro = true;
|
|
@@ -17900,28 +18266,30 @@ class SemanticAnalyzer {
|
|
|
17900
18266
|
}
|
|
17901
18267
|
}
|
|
17902
18268
|
extract_scalar_symbol(node, symbols, node_index) {
|
|
17903
|
-
|
|
18269
|
+
const varlist = this.semantic_varlist(node);
|
|
18270
|
+
if (varlist.length === 0) {
|
|
17904
18271
|
return;
|
|
17905
18272
|
}
|
|
17906
|
-
const scalar_name =
|
|
17907
|
-
this.add_or_append_definition(symbols.scalars, scalar_name, node_index,
|
|
18273
|
+
const scalar_name = varlist[0].name;
|
|
18274
|
+
this.add_or_append_definition(symbols.scalars, scalar_name, node_index, varlist[0].range, () => ({
|
|
17908
18275
|
name: scalar_name,
|
|
17909
|
-
location: { uri: this.uri, range:
|
|
18276
|
+
location: { uri: this.uri, range: varlist[0].range },
|
|
17910
18277
|
sourceUri: this.uri,
|
|
17911
|
-
definition_line:
|
|
18278
|
+
definition_line: varlist[0].range.start.line
|
|
17912
18279
|
}));
|
|
17913
18280
|
}
|
|
17914
18281
|
extract_matrix_symbol(node, symbols, node_index) {
|
|
17915
|
-
|
|
18282
|
+
const varlist = this.semantic_varlist(node);
|
|
18283
|
+
if (varlist.length === 0) {
|
|
17916
18284
|
return;
|
|
17917
18285
|
}
|
|
17918
|
-
const first =
|
|
17919
|
-
const second =
|
|
18286
|
+
const first = varlist[0]?.name;
|
|
18287
|
+
const second = varlist[1]?.name;
|
|
17920
18288
|
const matrix_name = first && first === "define" ? second : first;
|
|
17921
18289
|
if (!matrix_name) {
|
|
17922
18290
|
return;
|
|
17923
18291
|
}
|
|
17924
|
-
const name_range = first && first === "define" &&
|
|
18292
|
+
const name_range = first && first === "define" && varlist[1] ? varlist[1].range : varlist[0].range;
|
|
17925
18293
|
this.add_or_append_definition(symbols.matrices, matrix_name, node_index, name_range, () => ({
|
|
17926
18294
|
name: matrix_name,
|
|
17927
18295
|
location: { uri: this.uri, range: name_range },
|
|
@@ -17930,22 +18298,23 @@ class SemanticAnalyzer {
|
|
|
17930
18298
|
}));
|
|
17931
18299
|
}
|
|
17932
18300
|
pick_new_variable(node) {
|
|
17933
|
-
|
|
18301
|
+
const varlist = this.semantic_varlist(node);
|
|
18302
|
+
if (varlist.length === 0) {
|
|
17934
18303
|
return;
|
|
17935
18304
|
}
|
|
17936
|
-
if (is_stata_storage_type(
|
|
17937
|
-
if (
|
|
17938
|
-
return
|
|
18305
|
+
if (is_stata_storage_type(varlist[0].name)) {
|
|
18306
|
+
if (varlist.length > 1) {
|
|
18307
|
+
return varlist[1];
|
|
17939
18308
|
}
|
|
17940
18309
|
this.current_diagnostics.push({
|
|
17941
|
-
message: `Missing variable name after storage type \`${
|
|
17942
|
-
range:
|
|
18310
|
+
message: `Missing variable name after storage type \`${varlist[0].name}'`,
|
|
18311
|
+
range: varlist[0].range,
|
|
17943
18312
|
code: "MISSING_VARIABLE_NAME" /* MISSING_VARIABLE_NAME */,
|
|
17944
18313
|
severity: "error"
|
|
17945
18314
|
});
|
|
17946
18315
|
return;
|
|
17947
18316
|
}
|
|
17948
|
-
return
|
|
18317
|
+
return varlist[0];
|
|
17949
18318
|
}
|
|
17950
18319
|
extract_gen_variable(node, symbols) {
|
|
17951
18320
|
const new_var = this.pick_new_variable(node);
|
|
@@ -17978,10 +18347,11 @@ class SemanticAnalyzer {
|
|
|
17978
18347
|
symbols.variables.set(new_var.name, var_symbol);
|
|
17979
18348
|
}
|
|
17980
18349
|
extract_input_variables(node, symbols) {
|
|
17981
|
-
|
|
18350
|
+
const varlist = this.semantic_varlist(node);
|
|
18351
|
+
if (varlist.length === 0) {
|
|
17982
18352
|
return;
|
|
17983
18353
|
}
|
|
17984
|
-
for (const var_node of
|
|
18354
|
+
for (const var_node of varlist) {
|
|
17985
18355
|
if (this.is_macro_reference(var_node.name)) {
|
|
17986
18356
|
continue;
|
|
17987
18357
|
}
|
|
@@ -18018,28 +18388,29 @@ class SemanticAnalyzer {
|
|
|
18018
18388
|
return false;
|
|
18019
18389
|
}
|
|
18020
18390
|
extract_rename_variables(node, symbols) {
|
|
18021
|
-
|
|
18391
|
+
const varlist = this.semantic_varlist(node);
|
|
18392
|
+
if (varlist.length < 2) {
|
|
18022
18393
|
return;
|
|
18023
18394
|
}
|
|
18024
|
-
if (
|
|
18395
|
+
if (varlist.length !== 2 && !(varlist[0].name.startsWith("(") && varlist[1].name.startsWith("("))) {
|
|
18025
18396
|
return;
|
|
18026
18397
|
}
|
|
18027
|
-
const first_item =
|
|
18028
|
-
const second_item =
|
|
18398
|
+
const first_item = varlist[0].name;
|
|
18399
|
+
const second_item = varlist[1].name;
|
|
18029
18400
|
if (first_item.startsWith("(") && second_item.startsWith("(")) {
|
|
18030
18401
|
if (this.contains_wildcard(first_item) || this.contains_wildcard(second_item)) {
|
|
18031
18402
|
return;
|
|
18032
18403
|
}
|
|
18033
|
-
this.extract_grouped_rename_variables(second_item,
|
|
18404
|
+
this.extract_grouped_rename_variables(second_item, varlist[1].range, symbols);
|
|
18034
18405
|
return;
|
|
18035
18406
|
}
|
|
18036
18407
|
if (this.contains_wildcard(first_item) || this.contains_wildcard(second_item)) {
|
|
18037
18408
|
return;
|
|
18038
18409
|
}
|
|
18039
|
-
if (this.has_adjacent_wildcard_token(
|
|
18410
|
+
if (this.has_adjacent_wildcard_token(varlist[0].range) || this.has_adjacent_wildcard_token(varlist[1].range)) {
|
|
18040
18411
|
return;
|
|
18041
18412
|
}
|
|
18042
|
-
const new_var =
|
|
18413
|
+
const new_var = varlist[1];
|
|
18043
18414
|
if (this.is_macro_reference(new_var.name)) {
|
|
18044
18415
|
return;
|
|
18045
18416
|
}
|
|
@@ -18052,7 +18423,7 @@ class SemanticAnalyzer {
|
|
|
18052
18423
|
symbols.variables.set(new_var.name, var_symbol);
|
|
18053
18424
|
}
|
|
18054
18425
|
extract_grouped_rename_variables(group_content, group_range, symbols) {
|
|
18055
|
-
const inner = group_content.slice(1, -1).trim();
|
|
18426
|
+
const inner = (group_content.endsWith(")") ? group_content.slice(1, -1) : group_content.slice(1)).trim();
|
|
18056
18427
|
const the_names = inner.split(/\s+/).filter((n) => n.length > 0);
|
|
18057
18428
|
for (const my_name of the_names) {
|
|
18058
18429
|
if (this.contains_wildcard(my_name)) {
|
|
@@ -18071,14 +18442,15 @@ class SemanticAnalyzer {
|
|
|
18071
18442
|
}
|
|
18072
18443
|
}
|
|
18073
18444
|
extract_confirm_variable(node, symbols) {
|
|
18074
|
-
|
|
18445
|
+
const varlist = this.semantic_varlist(node);
|
|
18446
|
+
if (varlist.length < 2) {
|
|
18075
18447
|
return;
|
|
18076
18448
|
}
|
|
18077
|
-
const first_item =
|
|
18449
|
+
const first_item = varlist[0].name.toLowerCase();
|
|
18078
18450
|
if (first_item !== "variable" && first_item !== "var") {
|
|
18079
18451
|
return;
|
|
18080
18452
|
}
|
|
18081
|
-
const var_node =
|
|
18453
|
+
const var_node = varlist[1];
|
|
18082
18454
|
if (this.is_macro_reference(var_node.name)) {
|
|
18083
18455
|
return;
|
|
18084
18456
|
}
|
|
@@ -18091,10 +18463,11 @@ class SemanticAnalyzer {
|
|
|
18091
18463
|
symbols.variables.set(var_node.name, var_symbol);
|
|
18092
18464
|
}
|
|
18093
18465
|
extract_tempvar_macro(node, symbols, current_scope, node_index) {
|
|
18094
|
-
|
|
18466
|
+
const varlist = this.semantic_varlist(node);
|
|
18467
|
+
if (varlist.length === 0) {
|
|
18095
18468
|
return;
|
|
18096
18469
|
}
|
|
18097
|
-
for (const var_node of
|
|
18470
|
+
for (const var_node of varlist) {
|
|
18098
18471
|
this.register_local_macro(current_scope, symbols, var_node.name, node_index, var_node.range, () => ({
|
|
18099
18472
|
name: var_node.name,
|
|
18100
18473
|
scope: "local",
|
|
@@ -18107,8 +18480,9 @@ class SemanticAnalyzer {
|
|
|
18107
18480
|
}
|
|
18108
18481
|
}
|
|
18109
18482
|
extract_unab_macro(node, symbols, current_scope, node_index) {
|
|
18110
|
-
|
|
18111
|
-
|
|
18483
|
+
const varlist = this.semantic_varlist(node);
|
|
18484
|
+
if (varlist.length > 0) {
|
|
18485
|
+
const macro_node = varlist[0];
|
|
18112
18486
|
const macro_name = macro_node.name;
|
|
18113
18487
|
this.register_local_macro(current_scope, symbols, macro_name, node_index, macro_node.range, () => ({
|
|
18114
18488
|
name: macro_name,
|
|
@@ -18122,8 +18496,9 @@ class SemanticAnalyzer {
|
|
|
18122
18496
|
}
|
|
18123
18497
|
}
|
|
18124
18498
|
extract_args_macros(node, symbols, current_scope, node_index) {
|
|
18125
|
-
|
|
18126
|
-
|
|
18499
|
+
const varlist = this.semantic_varlist(node);
|
|
18500
|
+
if (varlist.length > 0) {
|
|
18501
|
+
for (const my_var_node of varlist) {
|
|
18127
18502
|
const macro_name = my_var_node.name;
|
|
18128
18503
|
this.register_local_macro(current_scope, symbols, macro_name, node_index, my_var_node.range, () => ({
|
|
18129
18504
|
name: macro_name,
|
|
@@ -18138,12 +18513,13 @@ class SemanticAnalyzer {
|
|
|
18138
18513
|
}
|
|
18139
18514
|
}
|
|
18140
18515
|
extract_gettoken_macros(node, symbols, current_scope, node_index) {
|
|
18141
|
-
|
|
18516
|
+
const varlist = this.semantic_varlist(node);
|
|
18517
|
+
if (varlist.length === 0) {
|
|
18142
18518
|
return;
|
|
18143
18519
|
}
|
|
18144
|
-
const max_macros = Math.min(
|
|
18520
|
+
const max_macros = Math.min(varlist.length, 2);
|
|
18145
18521
|
for (let i = 0;i < max_macros; i++) {
|
|
18146
|
-
const my_var_node =
|
|
18522
|
+
const my_var_node = varlist[i];
|
|
18147
18523
|
const macro_name = my_var_node.name;
|
|
18148
18524
|
if (!is_valid_identifier(macro_name)) {
|
|
18149
18525
|
continue;
|
|
@@ -18160,13 +18536,14 @@ class SemanticAnalyzer {
|
|
|
18160
18536
|
}
|
|
18161
18537
|
}
|
|
18162
18538
|
extract_file_read_macro(node, symbols, current_scope, node_index) {
|
|
18163
|
-
|
|
18539
|
+
const varlist = this.semantic_varlist(node);
|
|
18540
|
+
if (varlist.length < 3) {
|
|
18164
18541
|
return;
|
|
18165
18542
|
}
|
|
18166
|
-
if (
|
|
18543
|
+
if (varlist[0].name !== "read") {
|
|
18167
18544
|
return;
|
|
18168
18545
|
}
|
|
18169
|
-
const macro_node =
|
|
18546
|
+
const macro_node = varlist[2];
|
|
18170
18547
|
const macro_name = macro_node.name;
|
|
18171
18548
|
if (!is_valid_identifier(macro_name)) {
|
|
18172
18549
|
return;
|
|
@@ -18240,6 +18617,9 @@ class SemanticAnalyzer {
|
|
|
18240
18617
|
if (!builtin_cmd && !program_options)
|
|
18241
18618
|
return false;
|
|
18242
18619
|
for (const my_option of node.options) {
|
|
18620
|
+
if (my_option.argument_unclosed) {
|
|
18621
|
+
continue;
|
|
18622
|
+
}
|
|
18243
18623
|
let matches = false;
|
|
18244
18624
|
if (builtin_cmd) {
|
|
18245
18625
|
for (const opt of builtin_cmd.local_options) {
|
|
@@ -18266,7 +18646,7 @@ class SemanticAnalyzer {
|
|
|
18266
18646
|
if (node.fullName !== "macro" && node.fullName !== "mac") {
|
|
18267
18647
|
return { names: [], unknown: false };
|
|
18268
18648
|
}
|
|
18269
|
-
const the_args = node
|
|
18649
|
+
const the_args = this.semantic_varlist(node);
|
|
18270
18650
|
if (the_args.length < 2 || !/^dr(o(p)?)?$/.test(the_args[0].name)) {
|
|
18271
18651
|
return { names: [], unknown: false };
|
|
18272
18652
|
}
|
|
@@ -18297,18 +18677,20 @@ class SemanticAnalyzer {
|
|
|
18297
18677
|
names.push(name);
|
|
18298
18678
|
};
|
|
18299
18679
|
if (cmd_name === "tempvar" || cmd_name === "tempfile" || cmd_name === "tempname" || cmd_name === "args") {
|
|
18300
|
-
for (const my_var of node
|
|
18680
|
+
for (const my_var of this.semantic_varlist(node))
|
|
18301
18681
|
push_literal(my_var.name);
|
|
18302
18682
|
} else if (cmd_name === "unab") {
|
|
18303
|
-
push_literal(node
|
|
18683
|
+
push_literal(this.semantic_varlist(node)[0]?.name);
|
|
18304
18684
|
} else if (cmd_name === "gettoken" || cmd_name === "gettok") {
|
|
18305
|
-
const
|
|
18685
|
+
const varlist = this.semantic_varlist(node);
|
|
18686
|
+
const max_macros = Math.min(varlist.length, 2);
|
|
18306
18687
|
for (let i = 0;i < max_macros; i++) {
|
|
18307
|
-
push_literal(
|
|
18688
|
+
push_literal(varlist[i].name);
|
|
18308
18689
|
}
|
|
18309
18690
|
} else if (cmd_name === "file" || cmd_name === "fil" || cmd_name === "fi") {
|
|
18310
|
-
|
|
18311
|
-
|
|
18691
|
+
const varlist = this.semantic_varlist(node);
|
|
18692
|
+
if (varlist.length >= 3 && varlist[0].name === "read") {
|
|
18693
|
+
push_literal(varlist[2].name);
|
|
18312
18694
|
}
|
|
18313
18695
|
}
|
|
18314
18696
|
return names;
|
|
@@ -18347,6 +18729,9 @@ class SemanticAnalyzer {
|
|
|
18347
18729
|
}
|
|
18348
18730
|
const the_created = [];
|
|
18349
18731
|
for (const option of node.options) {
|
|
18732
|
+
if (option.argument_unclosed) {
|
|
18733
|
+
continue;
|
|
18734
|
+
}
|
|
18350
18735
|
const parse_result = parse_option_argument(option.argument);
|
|
18351
18736
|
if (!parse_result.is_literal || !parse_result.identifier) {
|
|
18352
18737
|
continue;
|
|
@@ -18696,19 +19081,17 @@ class SemanticAnalyzer {
|
|
|
18696
19081
|
if (cmd_name === "generate" || cmd_name === "gen" || cmd_name === "egen" || cmd_name === "input" || cmd_name === "tempvar" || cmd_name === "unab") {
|
|
18697
19082
|
return;
|
|
18698
19083
|
}
|
|
18699
|
-
|
|
18700
|
-
|
|
18701
|
-
|
|
18702
|
-
|
|
18703
|
-
|
|
18704
|
-
|
|
18705
|
-
|
|
18706
|
-
|
|
18707
|
-
|
|
18708
|
-
|
|
18709
|
-
|
|
18710
|
-
});
|
|
18711
|
-
}
|
|
19084
|
+
for (const var_node of this.semantic_varlist(node)) {
|
|
19085
|
+
const is_defined = this.is_variable_defined(var_node.name, symbols, var_node.range.start.line);
|
|
19086
|
+
if (!is_defined) {
|
|
19087
|
+
diagnostics.push({
|
|
19088
|
+
message: format_undefined_variable_message(var_node.name),
|
|
19089
|
+
range: var_node.range,
|
|
19090
|
+
code: "UNDEFINED_VARIABLE" /* UNDEFINED_VARIABLE */,
|
|
19091
|
+
severity: "information",
|
|
19092
|
+
symbol_name: var_node.name,
|
|
19093
|
+
reference_kind: "variable"
|
|
19094
|
+
});
|
|
18712
19095
|
}
|
|
18713
19096
|
}
|
|
18714
19097
|
}
|
|
@@ -19750,12 +20133,10 @@ class ContextTracker {
|
|
|
19750
20133
|
is_single_line: my_token.type === "MATA_INLINE"
|
|
19751
20134
|
};
|
|
19752
20135
|
if (my_token.type === "MATA_INLINE") {
|
|
19753
|
-
|
|
19754
|
-
|
|
19755
|
-
range: my_token.range
|
|
19756
|
-
};
|
|
19757
|
-
this.context_ranges.push(this.complete_context_range_from_token(my_current_range));
|
|
20136
|
+
const my_inline_end = inline_embedded_statement_end(tokens, my_i);
|
|
20137
|
+
this.context_ranges.push(this.complete_context_range_from_token(my_current_range, my_inline_end.end_line));
|
|
19758
20138
|
my_current_range = null;
|
|
20139
|
+
my_i = my_inline_end.end_index;
|
|
19759
20140
|
} else {
|
|
19760
20141
|
this.context_stack.push("mata" /* MATA */);
|
|
19761
20142
|
my_current_context = "mata" /* MATA */;
|
|
@@ -19777,12 +20158,10 @@ class ContextTracker {
|
|
|
19777
20158
|
is_single_line: my_token.type === "PYTHON_INLINE"
|
|
19778
20159
|
};
|
|
19779
20160
|
if (my_token.type === "PYTHON_INLINE") {
|
|
19780
|
-
|
|
19781
|
-
|
|
19782
|
-
range: my_token.range
|
|
19783
|
-
};
|
|
19784
|
-
this.context_ranges.push(this.complete_context_range_from_token(my_current_range));
|
|
20161
|
+
const my_inline_end = inline_embedded_statement_end(tokens, my_i);
|
|
20162
|
+
this.context_ranges.push(this.complete_context_range_from_token(my_current_range, my_inline_end.end_line));
|
|
19785
20163
|
my_current_range = null;
|
|
20164
|
+
my_i = my_inline_end.end_index;
|
|
19786
20165
|
} else {
|
|
19787
20166
|
this.context_stack.push("python" /* PYTHON */);
|
|
19788
20167
|
my_current_context = "python" /* PYTHON */;
|
|
@@ -20086,11 +20465,11 @@ class ContextTracker {
|
|
|
20086
20465
|
}
|
|
20087
20466
|
return false;
|
|
20088
20467
|
}
|
|
20089
|
-
complete_context_range_from_token(partial_range) {
|
|
20468
|
+
complete_context_range_from_token(partial_range, single_line_end_line) {
|
|
20090
20469
|
const my_start_line = partial_range.start_delimiter.range.start.line;
|
|
20091
20470
|
let my_end_line;
|
|
20092
20471
|
if (partial_range.is_single_line) {
|
|
20093
|
-
my_end_line = my_start_line;
|
|
20472
|
+
my_end_line = single_line_end_line ?? my_start_line;
|
|
20094
20473
|
} else {
|
|
20095
20474
|
if (partial_range.end_delimiter) {
|
|
20096
20475
|
my_end_line = partial_range.end_delimiter.range.start.line - 1;
|
|
@@ -20278,6 +20657,7 @@ var init_context_tracker = __esm(() => {
|
|
|
20278
20657
|
init_types2();
|
|
20279
20658
|
init_types();
|
|
20280
20659
|
init_block_comment_utils();
|
|
20660
|
+
init_statement_span();
|
|
20281
20661
|
CONTEXT_TRIVIA_TOKEN_TYPES = new Set([
|
|
20282
20662
|
"COMMENT_LINE",
|
|
20283
20663
|
"COMMENT_BLOCK",
|
|
@@ -20961,6 +21341,221 @@ var init_document_store = __esm(() => {
|
|
|
20961
21341
|
import_vscode_languageserver = __toESM(require_main4(), 1);
|
|
20962
21342
|
});
|
|
20963
21343
|
|
|
21344
|
+
// src/utils/lru-cache.ts
|
|
21345
|
+
class LRUCache {
|
|
21346
|
+
cache = new Map;
|
|
21347
|
+
max_size;
|
|
21348
|
+
hits = 0;
|
|
21349
|
+
misses = 0;
|
|
21350
|
+
evictions = 0;
|
|
21351
|
+
current_generation = 0;
|
|
21352
|
+
constructor(max_size = 100) {
|
|
21353
|
+
this.max_size = max_size;
|
|
21354
|
+
}
|
|
21355
|
+
get(key) {
|
|
21356
|
+
const entry = this.cache.get(key);
|
|
21357
|
+
if (entry !== undefined) {
|
|
21358
|
+
this.hits++;
|
|
21359
|
+
entry.access_count++;
|
|
21360
|
+
this.cache.delete(key);
|
|
21361
|
+
this.cache.set(key, entry);
|
|
21362
|
+
return entry.value;
|
|
21363
|
+
} else {
|
|
21364
|
+
this.misses++;
|
|
21365
|
+
}
|
|
21366
|
+
return;
|
|
21367
|
+
}
|
|
21368
|
+
set(key, value) {
|
|
21369
|
+
this.cache.delete(key);
|
|
21370
|
+
if (this.cache.size >= this.max_size) {
|
|
21371
|
+
this.evict_one();
|
|
21372
|
+
}
|
|
21373
|
+
this.cache.set(key, {
|
|
21374
|
+
value,
|
|
21375
|
+
generation: this.current_generation,
|
|
21376
|
+
access_count: 1
|
|
21377
|
+
});
|
|
21378
|
+
}
|
|
21379
|
+
evict_one() {
|
|
21380
|
+
let victim_key;
|
|
21381
|
+
let victim_score = Infinity;
|
|
21382
|
+
for (const [key, entry] of this.cache) {
|
|
21383
|
+
const score = entry.generation * 1000 + entry.access_count;
|
|
21384
|
+
if (score < victim_score) {
|
|
21385
|
+
victim_score = score;
|
|
21386
|
+
victim_key = key;
|
|
21387
|
+
}
|
|
21388
|
+
}
|
|
21389
|
+
if (victim_key !== undefined) {
|
|
21390
|
+
this.cache.delete(victim_key);
|
|
21391
|
+
this.evictions++;
|
|
21392
|
+
}
|
|
21393
|
+
}
|
|
21394
|
+
advance_generation() {
|
|
21395
|
+
this.current_generation++;
|
|
21396
|
+
}
|
|
21397
|
+
trim_to_top_n(n) {
|
|
21398
|
+
if (this.cache.size <= n)
|
|
21399
|
+
return;
|
|
21400
|
+
const entries = Array.from(this.cache.entries()).sort((a, b) => b[1].access_count - a[1].access_count);
|
|
21401
|
+
this.cache.clear();
|
|
21402
|
+
for (let i = 0;i < Math.min(n, entries.length); i++) {
|
|
21403
|
+
this.cache.set(entries[i][0], entries[i][1]);
|
|
21404
|
+
}
|
|
21405
|
+
this.evictions += entries.length - n;
|
|
21406
|
+
}
|
|
21407
|
+
has(key) {
|
|
21408
|
+
return this.cache.has(key);
|
|
21409
|
+
}
|
|
21410
|
+
clear() {
|
|
21411
|
+
this.cache.clear();
|
|
21412
|
+
}
|
|
21413
|
+
size() {
|
|
21414
|
+
return this.cache.size;
|
|
21415
|
+
}
|
|
21416
|
+
get_stats() {
|
|
21417
|
+
return { hits: this.hits, misses: this.misses, evictions: this.evictions };
|
|
21418
|
+
}
|
|
21419
|
+
}
|
|
21420
|
+
|
|
21421
|
+
class CompletionPrefixCache {
|
|
21422
|
+
cache;
|
|
21423
|
+
command_db_version = 0;
|
|
21424
|
+
workspace_version = 0;
|
|
21425
|
+
top_n_threshold;
|
|
21426
|
+
constructor(max_size = 100, top_n_threshold = 200) {
|
|
21427
|
+
this.cache = new LRUCache(max_size);
|
|
21428
|
+
this.top_n_threshold = top_n_threshold;
|
|
21429
|
+
}
|
|
21430
|
+
make_key(prefix, context, document_version = 0) {
|
|
21431
|
+
return `${context}:${prefix}:${this.command_db_version}:${this.workspace_version}:${document_version}`;
|
|
21432
|
+
}
|
|
21433
|
+
get_with_context(prefix, context, document_version = 0) {
|
|
21434
|
+
return this.cache.get(this.make_key(prefix, context, document_version));
|
|
21435
|
+
}
|
|
21436
|
+
set_with_context(prefix, context, value, document_version = 0) {
|
|
21437
|
+
const trimmed_value = this.apply_limit(value);
|
|
21438
|
+
this.cache.set(this.make_key(prefix, context, document_version), trimmed_value);
|
|
21439
|
+
return trimmed_value;
|
|
21440
|
+
}
|
|
21441
|
+
apply_limit(value) {
|
|
21442
|
+
if (this.top_n_threshold > 0 && value.length > this.top_n_threshold) {
|
|
21443
|
+
return value.slice(0, this.top_n_threshold);
|
|
21444
|
+
}
|
|
21445
|
+
return value;
|
|
21446
|
+
}
|
|
21447
|
+
has_with_context(prefix, context, document_version = 0) {
|
|
21448
|
+
return this.cache.has(this.make_key(prefix, context, document_version));
|
|
21449
|
+
}
|
|
21450
|
+
invalidate_on_db_change(new_version) {
|
|
21451
|
+
if (new_version !== this.command_db_version) {
|
|
21452
|
+
this.command_db_version = new_version;
|
|
21453
|
+
this.cache.clear();
|
|
21454
|
+
this.cache.advance_generation();
|
|
21455
|
+
}
|
|
21456
|
+
}
|
|
21457
|
+
invalidate_on_workspace_change(new_version) {
|
|
21458
|
+
if (new_version !== this.workspace_version) {
|
|
21459
|
+
this.workspace_version = new_version;
|
|
21460
|
+
this.cache.clear();
|
|
21461
|
+
this.cache.advance_generation();
|
|
21462
|
+
}
|
|
21463
|
+
}
|
|
21464
|
+
clear() {
|
|
21465
|
+
this.cache.clear();
|
|
21466
|
+
}
|
|
21467
|
+
size() {
|
|
21468
|
+
return this.cache.size();
|
|
21469
|
+
}
|
|
21470
|
+
get_stats() {
|
|
21471
|
+
return this.cache.get_stats();
|
|
21472
|
+
}
|
|
21473
|
+
}
|
|
21474
|
+
var BoundedLruMap;
|
|
21475
|
+
var init_lru_cache = __esm(() => {
|
|
21476
|
+
BoundedLruMap = class BoundedLruMap {
|
|
21477
|
+
map = new Map;
|
|
21478
|
+
max_size;
|
|
21479
|
+
on_evict;
|
|
21480
|
+
constructor(max_size, options) {
|
|
21481
|
+
this.max_size = Math.max(1, Math.floor(max_size));
|
|
21482
|
+
this.on_evict = options?.on_evict;
|
|
21483
|
+
}
|
|
21484
|
+
get(key) {
|
|
21485
|
+
if (!this.map.has(key)) {
|
|
21486
|
+
return;
|
|
21487
|
+
}
|
|
21488
|
+
const value = this.map.get(key);
|
|
21489
|
+
this.map.delete(key);
|
|
21490
|
+
this.map.set(key, value);
|
|
21491
|
+
return value;
|
|
21492
|
+
}
|
|
21493
|
+
peek(key) {
|
|
21494
|
+
return this.map.get(key);
|
|
21495
|
+
}
|
|
21496
|
+
has(key) {
|
|
21497
|
+
return this.map.has(key);
|
|
21498
|
+
}
|
|
21499
|
+
touch(key) {
|
|
21500
|
+
if (!this.map.has(key)) {
|
|
21501
|
+
return;
|
|
21502
|
+
}
|
|
21503
|
+
const value = this.map.get(key);
|
|
21504
|
+
this.map.delete(key);
|
|
21505
|
+
this.map.set(key, value);
|
|
21506
|
+
}
|
|
21507
|
+
set(key, value) {
|
|
21508
|
+
if (this.map.has(key)) {
|
|
21509
|
+
this.map.delete(key);
|
|
21510
|
+
} else if (this.map.size >= this.max_size) {
|
|
21511
|
+
this.evict_oldest();
|
|
21512
|
+
}
|
|
21513
|
+
this.map.set(key, value);
|
|
21514
|
+
return this;
|
|
21515
|
+
}
|
|
21516
|
+
delete(key) {
|
|
21517
|
+
return this.map.delete(key);
|
|
21518
|
+
}
|
|
21519
|
+
clear() {
|
|
21520
|
+
this.map.clear();
|
|
21521
|
+
}
|
|
21522
|
+
get size() {
|
|
21523
|
+
return this.map.size;
|
|
21524
|
+
}
|
|
21525
|
+
get capacity() {
|
|
21526
|
+
return this.max_size;
|
|
21527
|
+
}
|
|
21528
|
+
set_max_size(new_max_size) {
|
|
21529
|
+
this.max_size = Math.max(1, Math.floor(new_max_size));
|
|
21530
|
+
while (this.map.size > this.max_size) {
|
|
21531
|
+
this.evict_oldest();
|
|
21532
|
+
}
|
|
21533
|
+
}
|
|
21534
|
+
keys() {
|
|
21535
|
+
return this.map.keys();
|
|
21536
|
+
}
|
|
21537
|
+
values() {
|
|
21538
|
+
return this.map.values();
|
|
21539
|
+
}
|
|
21540
|
+
entries() {
|
|
21541
|
+
return this.map.entries();
|
|
21542
|
+
}
|
|
21543
|
+
[Symbol.iterator]() {
|
|
21544
|
+
return this.map[Symbol.iterator]();
|
|
21545
|
+
}
|
|
21546
|
+
evict_oldest() {
|
|
21547
|
+
const oldest = this.map.keys().next();
|
|
21548
|
+
if (oldest.done) {
|
|
21549
|
+
return;
|
|
21550
|
+
}
|
|
21551
|
+
const oldest_key = oldest.value;
|
|
21552
|
+
const oldest_value = this.map.get(oldest_key);
|
|
21553
|
+
this.map.delete(oldest_key);
|
|
21554
|
+
this.on_evict?.(oldest_key, oldest_value);
|
|
21555
|
+
}
|
|
21556
|
+
};
|
|
21557
|
+
});
|
|
21558
|
+
|
|
20964
21559
|
// src/utils/dofile-locals.ts
|
|
20965
21560
|
function is_dofile_local(symbol) {
|
|
20966
21561
|
return symbol.containingScope === "dofile";
|
|
@@ -21261,14 +21856,20 @@ class ForwardScopeResolver {
|
|
|
21261
21856
|
workspace_roots = [];
|
|
21262
21857
|
resolve_fs;
|
|
21263
21858
|
forward_closure_memo_enabled = true;
|
|
21264
|
-
forward_closure_memo = new
|
|
21859
|
+
forward_closure_memo = new BoundedLruMap(DEFAULT_MAX_CACHED_FORWARD_CLOSURES, {
|
|
21860
|
+
on_evict: (key, entry) => {
|
|
21861
|
+
this.memo_metrics.evictions++;
|
|
21862
|
+
this.prune_memo_uri_to_keys_for_entry(key, entry);
|
|
21863
|
+
}
|
|
21864
|
+
});
|
|
21265
21865
|
memo_uri_to_keys = new Map;
|
|
21266
21866
|
last_seen_graph_version;
|
|
21267
21867
|
memo_invalidation_epoch = 0;
|
|
21268
21868
|
memo_metrics = {
|
|
21269
21869
|
hits: 0,
|
|
21270
21870
|
misses: 0,
|
|
21271
|
-
invalidations: 0
|
|
21871
|
+
invalidations: 0,
|
|
21872
|
+
evictions: 0
|
|
21272
21873
|
};
|
|
21273
21874
|
standalone_in_flight = new Set;
|
|
21274
21875
|
active_probe_collectors = [];
|
|
@@ -21291,8 +21892,16 @@ class ForwardScopeResolver {
|
|
|
21291
21892
|
get_forward_closure_metrics() {
|
|
21292
21893
|
return { ...this.memo_metrics };
|
|
21293
21894
|
}
|
|
21895
|
+
get_forward_closure_memo_size() {
|
|
21896
|
+
return this.forward_closure_memo.size;
|
|
21897
|
+
}
|
|
21294
21898
|
reset_forward_closure_metrics() {
|
|
21295
|
-
this.memo_metrics = {
|
|
21899
|
+
this.memo_metrics = {
|
|
21900
|
+
hits: 0,
|
|
21901
|
+
misses: 0,
|
|
21902
|
+
invalidations: 0,
|
|
21903
|
+
evictions: 0
|
|
21904
|
+
};
|
|
21296
21905
|
}
|
|
21297
21906
|
invalidate_forward_closure_for_uri(uri) {
|
|
21298
21907
|
this.memo_invalidation_epoch++;
|
|
@@ -21316,12 +21925,16 @@ class ForwardScopeResolver {
|
|
|
21316
21925
|
this.memo_uri_to_keys.clear();
|
|
21317
21926
|
}
|
|
21318
21927
|
delete_memo_entry(key) {
|
|
21319
|
-
const my_entry = this.forward_closure_memo.
|
|
21928
|
+
const my_entry = this.forward_closure_memo.peek(key);
|
|
21320
21929
|
if (!my_entry) {
|
|
21321
21930
|
return false;
|
|
21322
21931
|
}
|
|
21323
21932
|
this.forward_closure_memo.delete(key);
|
|
21324
|
-
|
|
21933
|
+
this.prune_memo_uri_to_keys_for_entry(key, my_entry);
|
|
21934
|
+
return true;
|
|
21935
|
+
}
|
|
21936
|
+
prune_memo_uri_to_keys_for_entry(key, entry) {
|
|
21937
|
+
for (const my_dep_uri of entry.dependent_uris) {
|
|
21325
21938
|
const my_key_set = this.memo_uri_to_keys.get(my_dep_uri);
|
|
21326
21939
|
if (my_key_set) {
|
|
21327
21940
|
my_key_set.delete(key);
|
|
@@ -21330,7 +21943,9 @@ class ForwardScopeResolver {
|
|
|
21330
21943
|
}
|
|
21331
21944
|
}
|
|
21332
21945
|
}
|
|
21333
|
-
|
|
21946
|
+
}
|
|
21947
|
+
set_forward_closure_memo_capacity(max_entries) {
|
|
21948
|
+
this.forward_closure_memo.set_max_size(max_entries);
|
|
21334
21949
|
}
|
|
21335
21950
|
is_memo_usable() {
|
|
21336
21951
|
return this.dependency_graph === undefined || this.dependency_graph.is_scan_complete();
|
|
@@ -21743,6 +22358,10 @@ class ForwardScopeResolver {
|
|
|
21743
22358
|
});
|
|
21744
22359
|
}
|
|
21745
22360
|
store_memo_entry(key, entry) {
|
|
22361
|
+
const my_previous = this.forward_closure_memo.peek(key);
|
|
22362
|
+
if (my_previous) {
|
|
22363
|
+
this.prune_memo_uri_to_keys_for_entry(key, my_previous);
|
|
22364
|
+
}
|
|
21746
22365
|
this.forward_closure_memo.set(key, entry);
|
|
21747
22366
|
for (const my_dep_uri of entry.dependent_uris) {
|
|
21748
22367
|
let my_key_set = this.memo_uri_to_keys.get(my_dep_uri);
|
|
@@ -21916,13 +22535,14 @@ class ForwardScopeResolver {
|
|
|
21916
22535
|
this.clear_forward_closure_memo();
|
|
21917
22536
|
}
|
|
21918
22537
|
}
|
|
21919
|
-
var DEFAULT_CONFIG;
|
|
22538
|
+
var DEFAULT_CONFIG, DEFAULT_MAX_CACHED_FORWARD_CLOSURES = 2000;
|
|
21920
22539
|
var init_forward_scope_resolver = __esm(() => {
|
|
21921
22540
|
init_esm();
|
|
21922
22541
|
init_types();
|
|
21923
22542
|
init_analyzer();
|
|
21924
22543
|
init_file_path_utils();
|
|
21925
22544
|
init_workspace_roots();
|
|
22545
|
+
init_lru_cache();
|
|
21926
22546
|
init_dofile_locals();
|
|
21927
22547
|
init_visible_symbols();
|
|
21928
22548
|
DEFAULT_CONFIG = {
|
|
@@ -21981,13 +22601,23 @@ class ScopeResolver {
|
|
|
21981
22601
|
workspace_roots = [];
|
|
21982
22602
|
dependency_graph;
|
|
21983
22603
|
resolve_fs;
|
|
21984
|
-
constructor(logger2, content_provider) {
|
|
22604
|
+
constructor(logger2, content_provider, cache_capacities) {
|
|
21985
22605
|
this.directive_parser = new DirectiveParser;
|
|
21986
22606
|
this.lexer = new StataLexer;
|
|
21987
22607
|
this.parser = new StataParser;
|
|
21988
22608
|
this.analyzer = new SemanticAnalyzer;
|
|
21989
|
-
this.file_cache = new
|
|
21990
|
-
|
|
22609
|
+
this.file_cache = new BoundedLruMap(cache_capacities?.max_cached_files ?? DEFAULT_MAX_CACHED_FILES, {
|
|
22610
|
+
on_evict: (_key, entry) => {
|
|
22611
|
+
this.cache_metrics.file.evictions++;
|
|
22612
|
+
this.forward_scope_resolver?.invalidate_forward_closure_for_uri?.(entry.uri);
|
|
22613
|
+
}
|
|
22614
|
+
});
|
|
22615
|
+
this.scope_cache = new BoundedLruMap(cache_capacities?.max_cached_scopes ?? DEFAULT_MAX_CACHED_SCOPES, {
|
|
22616
|
+
on_evict: (key) => {
|
|
22617
|
+
this.cache_metrics.scope.evictions++;
|
|
22618
|
+
this.prune_uri_to_cache_keys_for_key(key);
|
|
22619
|
+
}
|
|
22620
|
+
});
|
|
21991
22621
|
this.uri_to_cache_keys = new Map;
|
|
21992
22622
|
this.cache_metrics = this.create_metrics();
|
|
21993
22623
|
this.logger = logger2;
|
|
@@ -22082,8 +22712,8 @@ class ScopeResolver {
|
|
|
22082
22712
|
}
|
|
22083
22713
|
create_metrics() {
|
|
22084
22714
|
const metrics = {
|
|
22085
|
-
scope: { hits: 0, misses: 0, invalidations: 0 },
|
|
22086
|
-
file: { hits: 0, misses: 0, invalidations: 0 }
|
|
22715
|
+
scope: { hits: 0, misses: 0, invalidations: 0, evictions: 0 },
|
|
22716
|
+
file: { hits: 0, misses: 0, invalidations: 0, evictions: 0 }
|
|
22087
22717
|
};
|
|
22088
22718
|
return {
|
|
22089
22719
|
...metrics,
|
|
@@ -22098,6 +22728,24 @@ class ScopeResolver {
|
|
|
22098
22728
|
}
|
|
22099
22729
|
};
|
|
22100
22730
|
}
|
|
22731
|
+
set_cache_capacities(capacities) {
|
|
22732
|
+
if (capacities.max_cached_files !== undefined) {
|
|
22733
|
+
this.file_cache.set_max_size(capacities.max_cached_files);
|
|
22734
|
+
}
|
|
22735
|
+
if (capacities.max_cached_scopes !== undefined) {
|
|
22736
|
+
this.scope_cache.set_max_size(capacities.max_cached_scopes);
|
|
22737
|
+
}
|
|
22738
|
+
}
|
|
22739
|
+
prune_uri_to_cache_keys_for_key(cache_key) {
|
|
22740
|
+
const key_uri = this.extract_uri_from_cache_key(cache_key);
|
|
22741
|
+
const key_set = this.uri_to_cache_keys.get(key_uri);
|
|
22742
|
+
if (key_set) {
|
|
22743
|
+
key_set.delete(cache_key);
|
|
22744
|
+
if (key_set.size === 0) {
|
|
22745
|
+
this.uri_to_cache_keys.delete(key_uri);
|
|
22746
|
+
}
|
|
22747
|
+
}
|
|
22748
|
+
}
|
|
22101
22749
|
make_file_cache_key(uri, working_directory) {
|
|
22102
22750
|
return working_directory ? `${uri}|${working_directory}` : uri;
|
|
22103
22751
|
}
|
|
@@ -22110,14 +22758,7 @@ class ScopeResolver {
|
|
|
22110
22758
|
}
|
|
22111
22759
|
for (const my_key of keys_to_remove) {
|
|
22112
22760
|
this.scope_cache.delete(my_key);
|
|
22113
|
-
|
|
22114
|
-
const key_set = this.uri_to_cache_keys.get(key_uri);
|
|
22115
|
-
if (key_set) {
|
|
22116
|
-
key_set.delete(my_key);
|
|
22117
|
-
if (key_set.size === 0) {
|
|
22118
|
-
this.uri_to_cache_keys.delete(key_uri);
|
|
22119
|
-
}
|
|
22120
|
-
}
|
|
22761
|
+
this.prune_uri_to_cache_keys_for_key(my_key);
|
|
22121
22762
|
}
|
|
22122
22763
|
return keys_to_remove.length;
|
|
22123
22764
|
}
|
|
@@ -22638,9 +23279,9 @@ class ScopeResolver {
|
|
|
22638
23279
|
...config,
|
|
22639
23280
|
backward_dependencies: "explicit"
|
|
22640
23281
|
};
|
|
22641
|
-
return this.discover_working_directory(the_backward_directives, new Set, 0, my_config, new Map, current_uri);
|
|
23282
|
+
return this.discover_working_directory(the_backward_directives, new Set, 0, my_config, new Map, current_uri, undefined, true);
|
|
22642
23283
|
}
|
|
22643
|
-
async discover_working_directory(directives, visited, depth, config, request_cache, current_uri, token) {
|
|
23284
|
+
async discover_working_directory(directives, visited, depth, config, request_cache, current_uri, token, skip_backward_registration) {
|
|
22644
23285
|
if (depth > config.max_backward_depth) {
|
|
22645
23286
|
return;
|
|
22646
23287
|
}
|
|
@@ -22661,7 +23302,8 @@ class ScopeResolver {
|
|
|
22661
23302
|
try {
|
|
22662
23303
|
my_parent_result = await this.get_parsed_file(my_parent_uri, my_real_path, {
|
|
22663
23304
|
request_cache,
|
|
22664
|
-
backward_dependencies: config.backward_dependencies ?? "auto"
|
|
23305
|
+
backward_dependencies: config.backward_dependencies ?? "auto",
|
|
23306
|
+
skip_backward_registration
|
|
22665
23307
|
});
|
|
22666
23308
|
} catch (error) {
|
|
22667
23309
|
my_parent_result = { error: String(error) };
|
|
@@ -22691,7 +23333,7 @@ class ScopeResolver {
|
|
|
22691
23333
|
} = this.get_effective_backward_directives(my_parent_uri, my_parent_result.directives, config, my_parent_result.is_standalone);
|
|
22692
23334
|
if (effective_parent_directives.length > 0) {
|
|
22693
23335
|
visited.add(my_parent_uri);
|
|
22694
|
-
const my_deeper_wd = await this.discover_working_directory(effective_parent_directives, visited, depth + 1, config, request_cache, my_parent_uri, token);
|
|
23336
|
+
const my_deeper_wd = await this.discover_working_directory(effective_parent_directives, visited, depth + 1, config, request_cache, my_parent_uri, token, skip_backward_registration);
|
|
22695
23337
|
visited.delete(my_parent_uri);
|
|
22696
23338
|
if (my_deeper_wd) {
|
|
22697
23339
|
return my_deeper_wd;
|
|
@@ -22930,8 +23572,9 @@ class ScopeResolver {
|
|
|
22930
23572
|
}
|
|
22931
23573
|
parse_file(uri, content) {
|
|
22932
23574
|
const content_hash = this.hash_content(content);
|
|
22933
|
-
const cached = this.file_cache.
|
|
23575
|
+
const cached = this.file_cache.peek(uri);
|
|
22934
23576
|
if (cached && cached.content_hash === content_hash) {
|
|
23577
|
+
this.file_cache.touch(uri);
|
|
22935
23578
|
return {
|
|
22936
23579
|
symbols: cached.symbols,
|
|
22937
23580
|
directives: cached.directives,
|
|
@@ -22948,6 +23591,7 @@ class ScopeResolver {
|
|
|
22948
23591
|
try {
|
|
22949
23592
|
const my_parse_result = this.parse_content(uri, content);
|
|
22950
23593
|
this.file_cache.set(uri, {
|
|
23594
|
+
uri,
|
|
22951
23595
|
content,
|
|
22952
23596
|
content_hash,
|
|
22953
23597
|
size: Buffer.byteLength(content, "utf8"),
|
|
@@ -23088,11 +23732,14 @@ class ScopeResolver {
|
|
|
23088
23732
|
async _get_parsed_file_impl(uri, fs_path, options) {
|
|
23089
23733
|
const inherited_wd = options?.working_directory;
|
|
23090
23734
|
const cache_key = this.make_file_cache_key(uri, inherited_wd);
|
|
23091
|
-
const cached = this.file_cache.
|
|
23735
|
+
const cached = this.file_cache.peek(cache_key);
|
|
23092
23736
|
if (options?.skip_disk_if_cached && cached) {
|
|
23093
23737
|
this.log(`[get_parsed_file] file_cache HIT for ${cache_key} (skip_disk_if_cached)`);
|
|
23094
23738
|
this.cache_metrics.file.hits++;
|
|
23095
|
-
this.
|
|
23739
|
+
this.file_cache.touch(cache_key);
|
|
23740
|
+
if (!options?.skip_backward_registration) {
|
|
23741
|
+
this.upgrade_registration_on_cache_hit(uri, cached, options?.backward_dependencies);
|
|
23742
|
+
}
|
|
23096
23743
|
return this.cache_entry_to_parsed_result(cached, cached.content, cached.content_hash);
|
|
23097
23744
|
}
|
|
23098
23745
|
let mtimeMs;
|
|
@@ -23104,7 +23751,10 @@ class ScopeResolver {
|
|
|
23104
23751
|
if (cached && mtimeMs !== undefined && size !== undefined && cached.mtimeMs !== undefined && cached.mtimeMs === mtimeMs && cached.size !== undefined && cached.size === size) {
|
|
23105
23752
|
this.cache_metrics.file.hits++;
|
|
23106
23753
|
this.log(`[get_parsed_file] File cache HIT for ${uri} (mtime match, skipped read)`);
|
|
23107
|
-
this.
|
|
23754
|
+
this.file_cache.touch(cache_key);
|
|
23755
|
+
if (!options?.skip_backward_registration) {
|
|
23756
|
+
this.upgrade_registration_on_cache_hit(uri, cached, options?.backward_dependencies);
|
|
23757
|
+
}
|
|
23108
23758
|
return this.cache_entry_to_parsed_result(cached, cached.content, cached.content_hash);
|
|
23109
23759
|
}
|
|
23110
23760
|
}
|
|
@@ -23122,11 +23772,14 @@ class ScopeResolver {
|
|
|
23122
23772
|
const fallback_mtimeMs = fallback_stats?.mtimeMs;
|
|
23123
23773
|
const fallback_size = fallback_stats?.size;
|
|
23124
23774
|
const fallback_cache_key = this.make_file_cache_key(fallback_uri, inherited_wd);
|
|
23125
|
-
const fallback_cached = this.file_cache.
|
|
23775
|
+
const fallback_cached = this.file_cache.peek(fallback_cache_key);
|
|
23126
23776
|
if (fallback_cached && fallback_mtimeMs !== undefined && fallback_size !== undefined && fallback_cached.mtimeMs !== undefined && fallback_cached.mtimeMs === fallback_mtimeMs && fallback_cached.size !== undefined && fallback_cached.size === fallback_size) {
|
|
23127
23777
|
this.cache_metrics.file.hits++;
|
|
23128
23778
|
this.log(`[get_parsed_file] File cache HIT for ${fallback_uri} (mtime match, skipped read)`);
|
|
23129
|
-
this.
|
|
23779
|
+
this.file_cache.touch(fallback_cache_key);
|
|
23780
|
+
if (!options?.skip_backward_registration) {
|
|
23781
|
+
this.upgrade_registration_on_cache_hit(fallback_uri, fallback_cached, options?.backward_dependencies);
|
|
23782
|
+
}
|
|
23130
23783
|
return this.cache_entry_to_parsed_result(fallback_cached, fallback_cached.content, fallback_cached.content_hash);
|
|
23131
23784
|
}
|
|
23132
23785
|
}
|
|
@@ -23145,12 +23798,15 @@ class ScopeResolver {
|
|
|
23145
23798
|
}
|
|
23146
23799
|
}
|
|
23147
23800
|
const actual_cache_key = this.make_file_cache_key(actual_uri, inherited_wd);
|
|
23148
|
-
const actual_cached = this.file_cache.
|
|
23801
|
+
const actual_cached = this.file_cache.peek(actual_cache_key);
|
|
23149
23802
|
const disk_hash = this.hash_content(content);
|
|
23150
23803
|
if (actual_cached && actual_cached.content_hash === disk_hash) {
|
|
23151
23804
|
this.cache_metrics.file.hits++;
|
|
23152
23805
|
this.log(`[get_parsed_file] File cache HIT for ${actual_uri} (hash match)`);
|
|
23153
|
-
this.
|
|
23806
|
+
this.file_cache.touch(actual_cache_key);
|
|
23807
|
+
if (!options?.skip_backward_registration) {
|
|
23808
|
+
this.upgrade_registration_on_cache_hit(actual_uri, actual_cached, options?.backward_dependencies);
|
|
23809
|
+
}
|
|
23154
23810
|
return this.cache_entry_to_parsed_result(actual_cached, content, disk_hash);
|
|
23155
23811
|
} else if (actual_cached) {
|
|
23156
23812
|
this.log(`[get_parsed_file] File cache STALE for ${actual_uri} (cached hash=${actual_cached.content_hash}, disk hash=${disk_hash})`);
|
|
@@ -23166,6 +23822,7 @@ class ScopeResolver {
|
|
|
23166
23822
|
mtimeMs = stats?.mtimeMs;
|
|
23167
23823
|
}
|
|
23168
23824
|
this.file_cache.set(actual_cache_key, {
|
|
23825
|
+
uri: actual_uri,
|
|
23169
23826
|
content,
|
|
23170
23827
|
content_hash: disk_hash,
|
|
23171
23828
|
mtimeMs,
|
|
@@ -23178,16 +23835,18 @@ class ScopeResolver {
|
|
|
23178
23835
|
working_directory_directive: parse_result.working_directory_directive,
|
|
23179
23836
|
is_standalone: parse_result.is_standalone,
|
|
23180
23837
|
diagnostics: parse_result.diagnostics,
|
|
23181
|
-
registered_backward_mode: options?.backward_dependencies ?? "explicit"
|
|
23838
|
+
registered_backward_mode: options?.skip_backward_registration ? undefined : options?.backward_dependencies ?? "explicit"
|
|
23182
23839
|
});
|
|
23183
|
-
|
|
23840
|
+
if (!options?.skip_backward_registration) {
|
|
23841
|
+
this.apply_backward_directive_registration(actual_uri, parse_result.directives, { backward_dependencies: options?.backward_dependencies ?? "explicit" }, parse_result.is_standalone);
|
|
23842
|
+
}
|
|
23184
23843
|
this.register_forward_call_relationships_from_cache(actual_uri, parse_result.forward_calls, parse_result.symbols);
|
|
23185
23844
|
return { content, content_hash: disk_hash, ...parse_result };
|
|
23186
23845
|
} catch (error) {
|
|
23187
23846
|
this.warn(`ScopeResolver: Parse error for ${actual_uri}: ${error_message(error)}`);
|
|
23188
23847
|
const empty_symbols = create_empty_symbol_table();
|
|
23189
23848
|
const my_recovered = this.recover_header_facts(actual_uri, content);
|
|
23190
|
-
if (my_recovered.recovered) {
|
|
23849
|
+
if (my_recovered.recovered && !options?.skip_backward_registration) {
|
|
23191
23850
|
this.apply_backward_directive_registration(actual_uri, my_recovered.directives, {
|
|
23192
23851
|
backward_dependencies: options?.backward_dependencies ?? "explicit"
|
|
23193
23852
|
}, my_recovered.is_standalone);
|
|
@@ -23429,6 +24088,12 @@ class ScopeResolver {
|
|
|
23429
24088
|
}
|
|
23430
24089
|
};
|
|
23431
24090
|
}
|
|
24091
|
+
get_cache_sizes() {
|
|
24092
|
+
return {
|
|
24093
|
+
scope: this.scope_cache.size,
|
|
24094
|
+
file: this.file_cache.size
|
|
24095
|
+
};
|
|
24096
|
+
}
|
|
23432
24097
|
reset_cache_metrics() {
|
|
23433
24098
|
this.cache_metrics = this.create_metrics();
|
|
23434
24099
|
}
|
|
@@ -23633,14 +24298,7 @@ class ScopeResolver {
|
|
|
23633
24298
|
}
|
|
23634
24299
|
for (const my_key of keys_to_remove) {
|
|
23635
24300
|
this.scope_cache.delete(my_key);
|
|
23636
|
-
|
|
23637
|
-
const key_set = this.uri_to_cache_keys.get(key_uri);
|
|
23638
|
-
if (key_set) {
|
|
23639
|
-
key_set.delete(my_key);
|
|
23640
|
-
if (key_set.size === 0) {
|
|
23641
|
-
this.uri_to_cache_keys.delete(key_uri);
|
|
23642
|
-
}
|
|
23643
|
-
}
|
|
24301
|
+
this.prune_uri_to_cache_keys_for_key(my_key);
|
|
23644
24302
|
this.cache_metrics.scope.invalidations++;
|
|
23645
24303
|
}
|
|
23646
24304
|
}
|
|
@@ -23694,6 +24352,10 @@ class ScopeResolver {
|
|
|
23694
24352
|
}
|
|
23695
24353
|
upgrade_registration_on_cache_hit(uri, cached, requested_mode) {
|
|
23696
24354
|
if (requested_mode !== "auto") {
|
|
24355
|
+
if (requested_mode === "explicit" && cached.registered_backward_mode === undefined) {
|
|
24356
|
+
this.apply_backward_directive_registration(uri, cached.directives, { backward_dependencies: "explicit" }, cached.is_standalone);
|
|
24357
|
+
cached.registered_backward_mode = "explicit";
|
|
24358
|
+
}
|
|
23697
24359
|
return;
|
|
23698
24360
|
}
|
|
23699
24361
|
if (cached.directives.length > 0 && cached.registered_backward_mode === "auto") {
|
|
@@ -23857,7 +24519,7 @@ class ScopeResolver {
|
|
|
23857
24519
|
this.reset_reverse_deps();
|
|
23858
24520
|
}
|
|
23859
24521
|
}
|
|
23860
|
-
var DEFAULT_CONFIG2;
|
|
24522
|
+
var DEFAULT_CONFIG2, DEFAULT_MAX_CACHED_FILES = 2000, DEFAULT_MAX_CACHED_SCOPES = 1000;
|
|
23861
24523
|
var init_scope_resolver = __esm(() => {
|
|
23862
24524
|
init_esm();
|
|
23863
24525
|
init_types();
|
|
@@ -23866,6 +24528,7 @@ var init_scope_resolver = __esm(() => {
|
|
|
23866
24528
|
init_parser();
|
|
23867
24529
|
init_analyzer();
|
|
23868
24530
|
init_logger();
|
|
24531
|
+
init_lru_cache();
|
|
23869
24532
|
init_dofile_locals();
|
|
23870
24533
|
init_workspace_roots();
|
|
23871
24534
|
init_file_path_utils();
|
|
@@ -27003,13 +27666,14 @@ class IndentationDiagnosticAnalyzer {
|
|
|
27003
27666
|
const stataRanges = this.getStataRanges(document);
|
|
27004
27667
|
const block_comment_lines2 = this.compute_block_comment_lines(lines, document.tokens);
|
|
27005
27668
|
const continuation_lines = document.tokens ? this.compute_continuation_lines(document.tokens) : new Set;
|
|
27669
|
+
const structural_taint = this.compute_structural_taint(document);
|
|
27006
27670
|
for (const range of stataRanges) {
|
|
27007
27671
|
diagnostics.push(...this.find_comment_indentation_issues(lines, range, block_comment_lines2, indent_size));
|
|
27008
27672
|
diagnostics.push(...this.find_block_indentation_issues(document, lines, range, block_comment_lines2, indent_size, continuation_lines));
|
|
27009
27673
|
const expected_depths = this.compute_expected_depths(document, range);
|
|
27010
|
-
diagnostics.push(...this.
|
|
27674
|
+
diagnostics.push(...this.find_ast_depth_indentation_issues(lines, range, block_comment_lines2, indent_size, expected_depths, continuation_lines, structural_taint));
|
|
27011
27675
|
}
|
|
27012
|
-
return diagnostics;
|
|
27676
|
+
return this.dedupe_by_line_and_code(diagnostics);
|
|
27013
27677
|
}
|
|
27014
27678
|
compute_continuation_lines(tokens) {
|
|
27015
27679
|
const continuation_lines = new Set;
|
|
@@ -27234,7 +27898,12 @@ class IndentationDiagnosticAnalyzer {
|
|
|
27234
27898
|
const is_control_flow = node.type === "program" || node.type === "if" || node.type === "else" || node.type === "foreach" || node.type === "forvalues" || node.type === "while" || node.type === "frame";
|
|
27235
27899
|
if (is_control_flow && node.body) {
|
|
27236
27900
|
for (const child of node.body) {
|
|
27237
|
-
|
|
27901
|
+
const child_start_line = child.range.start.line;
|
|
27902
|
+
if (child_start_line === start_line) {
|
|
27903
|
+
walk_node(child, current_depth);
|
|
27904
|
+
} else {
|
|
27905
|
+
walk_node(child, current_depth + 1);
|
|
27906
|
+
}
|
|
27238
27907
|
}
|
|
27239
27908
|
const end_line = node.range.end.line;
|
|
27240
27909
|
if (end_line !== start_line && end_line >= range.start && end_line <= range.end) {
|
|
@@ -27277,7 +27946,7 @@ class IndentationDiagnosticAnalyzer {
|
|
|
27277
27946
|
const block_node = node;
|
|
27278
27947
|
for (const my_child of block_node.body) {
|
|
27279
27948
|
const child_start_line = my_child.range.start.line;
|
|
27280
|
-
if (child_start_line === start_line
|
|
27949
|
+
if (child_start_line === start_line) {
|
|
27281
27950
|
walk_node(my_child, depth);
|
|
27282
27951
|
} else {
|
|
27283
27952
|
walk_node(my_child, depth + 1);
|
|
@@ -27319,14 +27988,15 @@ class IndentationDiagnosticAnalyzer {
|
|
|
27319
27988
|
}
|
|
27320
27989
|
return false;
|
|
27321
27990
|
}
|
|
27322
|
-
|
|
27991
|
+
find_ast_depth_indentation_issues(lines, range, block_comment_lines2, indent_size, expected_depths, continuation_lines, structural_taint) {
|
|
27323
27992
|
const diagnostics = [];
|
|
27324
27993
|
for (let i = range.start;i <= range.end && i < lines.length; i++) {
|
|
27325
27994
|
const line = lines[i];
|
|
27326
|
-
if (this.should_skip_unnecessary_check(line, i, block_comment_lines2, continuation_lines)) {
|
|
27995
|
+
if (this.should_skip_unnecessary_check(line, i, block_comment_lines2, continuation_lines) || structural_taint.has(i)) {
|
|
27327
27996
|
continue;
|
|
27328
27997
|
}
|
|
27329
27998
|
const actual_indent = this.get_line_indentation(line, indent_size);
|
|
27999
|
+
const has_known_depth = expected_depths.has(i);
|
|
27330
28000
|
const expected_depth = expected_depths.get(i) ?? 0;
|
|
27331
28001
|
const expected_indent = expected_depth * indent_size;
|
|
27332
28002
|
if (actual_indent > expected_indent) {
|
|
@@ -27338,12 +28008,94 @@ class IndentationDiagnosticAnalyzer {
|
|
|
27338
28008
|
code: "UNNECESSARY_INDENTATION" /* UNNECESSARY_INDENTATION */,
|
|
27339
28009
|
...diagnostic_code_description_fields("UNNECESSARY_INDENTATION" /* UNNECESSARY_INDENTATION */)
|
|
27340
28010
|
});
|
|
28011
|
+
} else if (has_known_depth && actual_indent < expected_indent) {
|
|
28012
|
+
diagnostics.push({
|
|
28013
|
+
severity: import_node.DiagnosticSeverity.Information,
|
|
28014
|
+
range: import_node.Range.create(import_node.Position.create(i, 0), import_node.Position.create(i, actual_indent)),
|
|
28015
|
+
message: "Line appears under-indented for its block depth. Use Format Document to fix.",
|
|
28016
|
+
source: "sight",
|
|
28017
|
+
code: "MISSING_INDENTATION" /* MISSING_INDENTATION */,
|
|
28018
|
+
...diagnostic_code_description_fields("MISSING_INDENTATION" /* MISSING_INDENTATION */)
|
|
28019
|
+
});
|
|
27341
28020
|
}
|
|
27342
28021
|
}
|
|
27343
28022
|
return diagnostics;
|
|
27344
28023
|
}
|
|
28024
|
+
compute_structural_taint(document) {
|
|
28025
|
+
const tainted_lines = new Set;
|
|
28026
|
+
const the_error_lines = [];
|
|
28027
|
+
for (const my_diagnostic of document.diagnostics) {
|
|
28028
|
+
const my_code = typeof my_diagnostic.code === "string" ? my_diagnostic.code : "";
|
|
28029
|
+
if (STRUCTURAL_NESTING_ERROR_CODES.has(my_code)) {
|
|
28030
|
+
the_error_lines.push(my_diagnostic.range.start.line);
|
|
28031
|
+
}
|
|
28032
|
+
}
|
|
28033
|
+
if (the_error_lines.length === 0) {
|
|
28034
|
+
return tainted_lines;
|
|
28035
|
+
}
|
|
28036
|
+
if (!document.ast) {
|
|
28037
|
+
for (const my_error_line of the_error_lines) {
|
|
28038
|
+
tainted_lines.add(my_error_line);
|
|
28039
|
+
}
|
|
28040
|
+
return tainted_lines;
|
|
28041
|
+
}
|
|
28042
|
+
for (const my_error_line of the_error_lines) {
|
|
28043
|
+
const my_block = this.find_smallest_block_containing(document.ast, my_error_line);
|
|
28044
|
+
if (my_block) {
|
|
28045
|
+
for (let my_line = my_block.range.start.line;my_line <= my_block.range.end.line; my_line++) {
|
|
28046
|
+
tainted_lines.add(my_line);
|
|
28047
|
+
}
|
|
28048
|
+
} else {
|
|
28049
|
+
tainted_lines.add(my_error_line);
|
|
28050
|
+
}
|
|
28051
|
+
}
|
|
28052
|
+
return tainted_lines;
|
|
28053
|
+
}
|
|
28054
|
+
find_smallest_block_containing(ast, line) {
|
|
28055
|
+
let best = null;
|
|
28056
|
+
const walk = (node) => {
|
|
28057
|
+
const start_line = node.range.start.line;
|
|
28058
|
+
const end_line = node.range.end.line;
|
|
28059
|
+
if (line < start_line || line > end_line) {
|
|
28060
|
+
return;
|
|
28061
|
+
}
|
|
28062
|
+
if (this.is_indentation_block_node(node)) {
|
|
28063
|
+
if (best === null || end_line - start_line <= best.range.end.line - best.range.start.line) {
|
|
28064
|
+
best = node;
|
|
28065
|
+
}
|
|
28066
|
+
}
|
|
28067
|
+
if ("body" in node && Array.isArray(node.body)) {
|
|
28068
|
+
for (const my_child of node.body) {
|
|
28069
|
+
walk(my_child);
|
|
28070
|
+
}
|
|
28071
|
+
}
|
|
28072
|
+
};
|
|
28073
|
+
for (const my_node of ast.nodes) {
|
|
28074
|
+
walk(my_node);
|
|
28075
|
+
}
|
|
28076
|
+
return best;
|
|
28077
|
+
}
|
|
28078
|
+
is_indentation_block_node(node) {
|
|
28079
|
+
if (this.is_block_node_type(node)) {
|
|
28080
|
+
return true;
|
|
28081
|
+
}
|
|
28082
|
+
return node.type === "command" && "name" in node && node.name === "{";
|
|
28083
|
+
}
|
|
28084
|
+
dedupe_by_line_and_code(diagnostics) {
|
|
28085
|
+
const seen_line_codes = new Set;
|
|
28086
|
+
const deduped = [];
|
|
28087
|
+
for (const my_diagnostic of diagnostics) {
|
|
28088
|
+
const my_key = `${my_diagnostic.range.start.line}:${my_diagnostic.code}`;
|
|
28089
|
+
if (seen_line_codes.has(my_key)) {
|
|
28090
|
+
continue;
|
|
28091
|
+
}
|
|
28092
|
+
seen_line_codes.add(my_key);
|
|
28093
|
+
deduped.push(my_diagnostic);
|
|
28094
|
+
}
|
|
28095
|
+
return deduped;
|
|
28096
|
+
}
|
|
27345
28097
|
}
|
|
27346
|
-
var import_node, CONTROL_FLOW_RE, FIRST_WORD_RE;
|
|
28098
|
+
var import_node, CONTROL_FLOW_RE, FIRST_WORD_RE, STRUCTURAL_NESTING_ERROR_CODES;
|
|
27347
28099
|
var init_indentation_diagnostics = __esm(() => {
|
|
27348
28100
|
init_types2();
|
|
27349
28101
|
init_types();
|
|
@@ -27351,6 +28103,17 @@ var init_indentation_diagnostics = __esm(() => {
|
|
|
27351
28103
|
import_node = __toESM(require_main4(), 1);
|
|
27352
28104
|
CONTROL_FLOW_RE = /^(if|foreach|while|program|mata|python)\b/;
|
|
27353
28105
|
FIRST_WORD_RE = /^(\w+)\b/;
|
|
28106
|
+
STRUCTURAL_NESTING_ERROR_CODES = new Set([
|
|
28107
|
+
"OPEN_BRACE_ALONE",
|
|
28108
|
+
"ORPHAN_CLOSE_BRACE",
|
|
28109
|
+
"BRACE_NOT_ALONE",
|
|
28110
|
+
"BRACE_ELSE_SAME_LINE",
|
|
28111
|
+
"CODE_AFTER_OPEN_BRACE",
|
|
28112
|
+
"UNCLOSED_BLOCK",
|
|
28113
|
+
"MISSING_PROGRAM_END",
|
|
28114
|
+
"UNBALANCED_QUOTES",
|
|
28115
|
+
"UNBALANCED_BLOCK_COMMENT"
|
|
28116
|
+
]);
|
|
27354
28117
|
});
|
|
27355
28118
|
|
|
27356
28119
|
// src/utils/diagnostic-severity.ts
|
|
@@ -29930,137 +30693,6 @@ var init_command_database = __esm(() => {
|
|
|
29930
30693
|
command_database = new CommandDatabase;
|
|
29931
30694
|
});
|
|
29932
30695
|
|
|
29933
|
-
// src/utils/lru-cache.ts
|
|
29934
|
-
class LRUCache {
|
|
29935
|
-
cache = new Map;
|
|
29936
|
-
max_size;
|
|
29937
|
-
hits = 0;
|
|
29938
|
-
misses = 0;
|
|
29939
|
-
evictions = 0;
|
|
29940
|
-
current_generation = 0;
|
|
29941
|
-
constructor(max_size = 100) {
|
|
29942
|
-
this.max_size = max_size;
|
|
29943
|
-
}
|
|
29944
|
-
get(key) {
|
|
29945
|
-
const entry = this.cache.get(key);
|
|
29946
|
-
if (entry !== undefined) {
|
|
29947
|
-
this.hits++;
|
|
29948
|
-
entry.access_count++;
|
|
29949
|
-
this.cache.delete(key);
|
|
29950
|
-
this.cache.set(key, entry);
|
|
29951
|
-
return entry.value;
|
|
29952
|
-
} else {
|
|
29953
|
-
this.misses++;
|
|
29954
|
-
}
|
|
29955
|
-
return;
|
|
29956
|
-
}
|
|
29957
|
-
set(key, value) {
|
|
29958
|
-
this.cache.delete(key);
|
|
29959
|
-
if (this.cache.size >= this.max_size) {
|
|
29960
|
-
this.evict_one();
|
|
29961
|
-
}
|
|
29962
|
-
this.cache.set(key, {
|
|
29963
|
-
value,
|
|
29964
|
-
generation: this.current_generation,
|
|
29965
|
-
access_count: 1
|
|
29966
|
-
});
|
|
29967
|
-
}
|
|
29968
|
-
evict_one() {
|
|
29969
|
-
let victim_key;
|
|
29970
|
-
let victim_score = Infinity;
|
|
29971
|
-
for (const [key, entry] of this.cache) {
|
|
29972
|
-
const score = entry.generation * 1000 + entry.access_count;
|
|
29973
|
-
if (score < victim_score) {
|
|
29974
|
-
victim_score = score;
|
|
29975
|
-
victim_key = key;
|
|
29976
|
-
}
|
|
29977
|
-
}
|
|
29978
|
-
if (victim_key !== undefined) {
|
|
29979
|
-
this.cache.delete(victim_key);
|
|
29980
|
-
this.evictions++;
|
|
29981
|
-
}
|
|
29982
|
-
}
|
|
29983
|
-
advance_generation() {
|
|
29984
|
-
this.current_generation++;
|
|
29985
|
-
}
|
|
29986
|
-
trim_to_top_n(n) {
|
|
29987
|
-
if (this.cache.size <= n)
|
|
29988
|
-
return;
|
|
29989
|
-
const entries = Array.from(this.cache.entries()).sort((a, b) => b[1].access_count - a[1].access_count);
|
|
29990
|
-
this.cache.clear();
|
|
29991
|
-
for (let i = 0;i < Math.min(n, entries.length); i++) {
|
|
29992
|
-
this.cache.set(entries[i][0], entries[i][1]);
|
|
29993
|
-
}
|
|
29994
|
-
this.evictions += entries.length - n;
|
|
29995
|
-
}
|
|
29996
|
-
has(key) {
|
|
29997
|
-
return this.cache.has(key);
|
|
29998
|
-
}
|
|
29999
|
-
clear() {
|
|
30000
|
-
this.cache.clear();
|
|
30001
|
-
}
|
|
30002
|
-
size() {
|
|
30003
|
-
return this.cache.size;
|
|
30004
|
-
}
|
|
30005
|
-
get_stats() {
|
|
30006
|
-
return { hits: this.hits, misses: this.misses, evictions: this.evictions };
|
|
30007
|
-
}
|
|
30008
|
-
}
|
|
30009
|
-
|
|
30010
|
-
class CompletionPrefixCache {
|
|
30011
|
-
cache;
|
|
30012
|
-
command_db_version = 0;
|
|
30013
|
-
workspace_version = 0;
|
|
30014
|
-
top_n_threshold;
|
|
30015
|
-
constructor(max_size = 100, top_n_threshold = 200) {
|
|
30016
|
-
this.cache = new LRUCache(max_size);
|
|
30017
|
-
this.top_n_threshold = top_n_threshold;
|
|
30018
|
-
}
|
|
30019
|
-
make_key(prefix, context, document_version = 0) {
|
|
30020
|
-
return `${context}:${prefix}:${this.command_db_version}:${this.workspace_version}:${document_version}`;
|
|
30021
|
-
}
|
|
30022
|
-
get_with_context(prefix, context, document_version = 0) {
|
|
30023
|
-
return this.cache.get(this.make_key(prefix, context, document_version));
|
|
30024
|
-
}
|
|
30025
|
-
set_with_context(prefix, context, value, document_version = 0) {
|
|
30026
|
-
const trimmed_value = this.apply_limit(value);
|
|
30027
|
-
this.cache.set(this.make_key(prefix, context, document_version), trimmed_value);
|
|
30028
|
-
return trimmed_value;
|
|
30029
|
-
}
|
|
30030
|
-
apply_limit(value) {
|
|
30031
|
-
if (this.top_n_threshold > 0 && value.length > this.top_n_threshold) {
|
|
30032
|
-
return value.slice(0, this.top_n_threshold);
|
|
30033
|
-
}
|
|
30034
|
-
return value;
|
|
30035
|
-
}
|
|
30036
|
-
has_with_context(prefix, context, document_version = 0) {
|
|
30037
|
-
return this.cache.has(this.make_key(prefix, context, document_version));
|
|
30038
|
-
}
|
|
30039
|
-
invalidate_on_db_change(new_version) {
|
|
30040
|
-
if (new_version !== this.command_db_version) {
|
|
30041
|
-
this.command_db_version = new_version;
|
|
30042
|
-
this.cache.clear();
|
|
30043
|
-
this.cache.advance_generation();
|
|
30044
|
-
}
|
|
30045
|
-
}
|
|
30046
|
-
invalidate_on_workspace_change(new_version) {
|
|
30047
|
-
if (new_version !== this.workspace_version) {
|
|
30048
|
-
this.workspace_version = new_version;
|
|
30049
|
-
this.cache.clear();
|
|
30050
|
-
this.cache.advance_generation();
|
|
30051
|
-
}
|
|
30052
|
-
}
|
|
30053
|
-
clear() {
|
|
30054
|
-
this.cache.clear();
|
|
30055
|
-
}
|
|
30056
|
-
size() {
|
|
30057
|
-
return this.cache.size();
|
|
30058
|
-
}
|
|
30059
|
-
get_stats() {
|
|
30060
|
-
return this.cache.get_stats();
|
|
30061
|
-
}
|
|
30062
|
-
}
|
|
30063
|
-
|
|
30064
30696
|
// src/utils/symbol-index-cache.ts
|
|
30065
30697
|
class SymbolIndexCache {
|
|
30066
30698
|
filtered_views = new Map;
|
|
@@ -30429,12 +31061,58 @@ function compute_ranking_key(factors) {
|
|
|
30429
31061
|
const name = factors.alphabetical_order.toLowerCase();
|
|
30430
31062
|
return `${scope_priority}${directive_priority}${symbol_priority_padded}|${parent_uri}|${name}`;
|
|
30431
31063
|
}
|
|
31064
|
+
function stata_region_floor_line(document, position) {
|
|
31065
|
+
const the_ranges = document.context_ranges;
|
|
31066
|
+
if (!the_ranges || the_ranges.length === 0) {
|
|
31067
|
+
return 0;
|
|
31068
|
+
}
|
|
31069
|
+
let floor_line = 0;
|
|
31070
|
+
for (const my_range of the_ranges) {
|
|
31071
|
+
if (my_range.context === "stata" /* STATA */) {
|
|
31072
|
+
continue;
|
|
31073
|
+
}
|
|
31074
|
+
if (my_range.start_delimiter?.command?.endsWith(":")) {
|
|
31075
|
+
continue;
|
|
31076
|
+
}
|
|
31077
|
+
if (my_range.range.end.line < position.line) {
|
|
31078
|
+
floor_line = Math.max(floor_line, my_range.range.end.line + 1);
|
|
31079
|
+
}
|
|
31080
|
+
}
|
|
31081
|
+
return floor_line;
|
|
31082
|
+
}
|
|
31083
|
+
function build_logical_text_before_cursor(document, position, tokens, start, physical_text_before_cursor) {
|
|
31084
|
+
if (start === undefined || tokens === undefined) {
|
|
31085
|
+
return physical_text_before_cursor;
|
|
31086
|
+
}
|
|
31087
|
+
const current_line = get_line_text(document, position.line);
|
|
31088
|
+
const physical_current = current_line.substring(start.line === position.line ? start.character : 0, position.character);
|
|
31089
|
+
if (start.line === position.line) {
|
|
31090
|
+
return physical_current;
|
|
31091
|
+
}
|
|
31092
|
+
const the_parts = [];
|
|
31093
|
+
for (let my_i = start.index;my_i < tokens.length && tokens[my_i].range.start.line < position.line; my_i++) {
|
|
31094
|
+
const my_token = tokens[my_i];
|
|
31095
|
+
if (LOGICAL_FLATTEN_SKIP_TYPES.has(my_token.type)) {
|
|
31096
|
+
continue;
|
|
31097
|
+
}
|
|
31098
|
+
the_parts.push(my_token.value);
|
|
31099
|
+
}
|
|
31100
|
+
const prior_text = the_parts.join(" ");
|
|
31101
|
+
return prior_text === "" ? physical_current : prior_text + " " + physical_current;
|
|
31102
|
+
}
|
|
30432
31103
|
function detect_completion_context(document, position, tokens, command_db) {
|
|
30433
31104
|
if (position.line >= get_line_count(document)) {
|
|
30434
31105
|
return { type: "fallback" };
|
|
30435
31106
|
}
|
|
30436
31107
|
const current_line = get_line_text(document, position.line);
|
|
30437
31108
|
const text_before_cursor = current_line.substring(0, position.character);
|
|
31109
|
+
let cached_logical_text;
|
|
31110
|
+
const get_logical_text = () => {
|
|
31111
|
+
if (cached_logical_text === undefined) {
|
|
31112
|
+
cached_logical_text = build_logical_text_before_cursor(document, position, tokens, logical_statement_start(tokens, position, stata_region_floor_line(document, position)), text_before_cursor);
|
|
31113
|
+
}
|
|
31114
|
+
return cached_logical_text;
|
|
31115
|
+
};
|
|
30438
31116
|
const extended_macro_context = detect_extended_macro_context(text_before_cursor, position);
|
|
30439
31117
|
if (extended_macro_context) {
|
|
30440
31118
|
return extended_macro_context;
|
|
@@ -30443,7 +31121,7 @@ function detect_completion_context(document, position, tokens, command_db) {
|
|
|
30443
31121
|
if (directive_context && !is_cursor_in_block_comment(document, position)) {
|
|
30444
31122
|
return directive_context;
|
|
30445
31123
|
}
|
|
30446
|
-
const command_path_context = detect_command_path_context(
|
|
31124
|
+
const command_path_context = detect_command_path_context(get_logical_text());
|
|
30447
31125
|
if (command_path_context) {
|
|
30448
31126
|
return command_path_context;
|
|
30449
31127
|
}
|
|
@@ -30451,18 +31129,18 @@ function detect_completion_context(document, position, tokens, command_db) {
|
|
|
30451
31129
|
if (macro_context) {
|
|
30452
31130
|
return macro_context;
|
|
30453
31131
|
}
|
|
30454
|
-
const option_context = detect_option_context(
|
|
31132
|
+
const option_context = detect_option_context(get_logical_text(), document, position);
|
|
30455
31133
|
if (option_context) {
|
|
30456
31134
|
return option_context;
|
|
30457
31135
|
}
|
|
30458
|
-
const subcommand_context = detect_subcommand_context(
|
|
31136
|
+
const subcommand_context = detect_subcommand_context(get_logical_text(), command_db);
|
|
30459
31137
|
if (subcommand_context) {
|
|
30460
31138
|
return subcommand_context;
|
|
30461
31139
|
}
|
|
30462
|
-
if (is_command_context(
|
|
31140
|
+
if (is_command_context(get_logical_text())) {
|
|
30463
31141
|
return { type: "command" };
|
|
30464
31142
|
}
|
|
30465
|
-
if (is_variable_context(
|
|
31143
|
+
if (is_variable_context(get_logical_text())) {
|
|
30466
31144
|
return { type: "variable" };
|
|
30467
31145
|
}
|
|
30468
31146
|
return { type: "fallback" };
|
|
@@ -30575,6 +31253,9 @@ function extract_command_name(text) {
|
|
|
30575
31253
|
}
|
|
30576
31254
|
const the_words = working_text.split(/\s+/).filter((w) => w.length > 0);
|
|
30577
31255
|
for (const my_word of the_words) {
|
|
31256
|
+
if (my_word === ":") {
|
|
31257
|
+
continue;
|
|
31258
|
+
}
|
|
30578
31259
|
const lower_word = my_word.toLowerCase();
|
|
30579
31260
|
if (!PREFIX_COMMANDS2.includes(lower_word)) {
|
|
30580
31261
|
return my_word;
|
|
@@ -30866,7 +31547,7 @@ class CompletionProvider {
|
|
|
30866
31547
|
if (my_current_context === "stata" /* STATA */ && is_cursor_in_block_comment(document, position, { require_tokens: true })) {
|
|
30867
31548
|
return [];
|
|
30868
31549
|
}
|
|
30869
|
-
const context = detect_completion_context(document, position, undefined, this.command_db);
|
|
31550
|
+
const context = detect_completion_context(document, position, my_current_context === "stata" /* STATA */ ? document.tokens : undefined, this.command_db);
|
|
30870
31551
|
if (my_current_context !== "stata" /* STATA */ && context.type !== "macro") {
|
|
30871
31552
|
const my_boundary_completions = this.get_block_boundary_completions(document, position);
|
|
30872
31553
|
return my_boundary_completions;
|
|
@@ -31202,7 +31883,8 @@ class CompletionProvider {
|
|
|
31202
31883
|
return "";
|
|
31203
31884
|
}
|
|
31204
31885
|
const current_line = get_line_text(document, position.line);
|
|
31205
|
-
const
|
|
31886
|
+
const physical_text_before_cursor = current_line.substring(0, position.character);
|
|
31887
|
+
const text_before_cursor = build_logical_text_before_cursor(document, position, document.tokens, logical_statement_start(document.tokens, position, stata_region_floor_line(document, position)), physical_text_before_cursor);
|
|
31206
31888
|
let paren_depth = 0;
|
|
31207
31889
|
let in_string = false;
|
|
31208
31890
|
let last_comma_pos = -1;
|
|
@@ -32216,12 +32898,13 @@ class CompletionProvider {
|
|
|
32216
32898
|
return position.line >= body_start && position.line < program.range.end.line;
|
|
32217
32899
|
}
|
|
32218
32900
|
}
|
|
32219
|
-
var import_vscode_languageserver4, DIRECTIVE_PATH_CONTEXT_PATTERN;
|
|
32901
|
+
var import_vscode_languageserver4, DIRECTIVE_PATH_CONTEXT_PATTERN, LOGICAL_FLATTEN_SKIP_TYPES;
|
|
32220
32902
|
var init_completion = __esm(() => {
|
|
32221
32903
|
init_command_database();
|
|
32222
32904
|
init_scoped_locals();
|
|
32223
32905
|
init_dofile_locals();
|
|
32224
32906
|
init_types2();
|
|
32907
|
+
init_lru_cache();
|
|
32225
32908
|
init_scope_resolver();
|
|
32226
32909
|
init_scope_resolver();
|
|
32227
32910
|
init_analyzer();
|
|
@@ -32230,8 +32913,18 @@ var init_completion = __esm(() => {
|
|
|
32230
32913
|
init_comment_utils();
|
|
32231
32914
|
init_logger();
|
|
32232
32915
|
init_macro_completion();
|
|
32916
|
+
init_statement_span();
|
|
32233
32917
|
import_vscode_languageserver4 = __toESM(require_main4(), 1);
|
|
32234
32918
|
DIRECTIVE_PATH_CONTEXT_PATTERN = new RegExp(`^\\s*(${DIRECTIVE_BODY_PREFIX_PATTERN}[a-zA-Z-]+)\\s*:?\\s*(.*)$`);
|
|
32919
|
+
LOGICAL_FLATTEN_SKIP_TYPES = new Set([
|
|
32920
|
+
"WHITESPACE",
|
|
32921
|
+
"COMMENT_LINE",
|
|
32922
|
+
"COMMENT_BLOCK",
|
|
32923
|
+
"CONTINUATION",
|
|
32924
|
+
"STATEMENT_TERMINATOR",
|
|
32925
|
+
"DELIMIT_DIRECTIVE",
|
|
32926
|
+
"EOF"
|
|
32927
|
+
]);
|
|
32235
32928
|
});
|
|
32236
32929
|
|
|
32237
32930
|
// src/utils/marker-scanner.ts
|
|
@@ -32495,7 +33188,8 @@ function create_completion_handler(deps) {
|
|
|
32495
33188
|
const config = await deps.get_document_settings(params.textDocument.uri);
|
|
32496
33189
|
const graph_version = deps.dependency_graph ? deps.dependency_graph.get_version() : undefined;
|
|
32497
33190
|
const items = await deps.completion_provider.get_completions(document_state, params.position, trigger_character, deps.scope_resolver || undefined, workspace_symbols, scope_resolver_config_for(config), workspace_version, token, graph_version);
|
|
32498
|
-
const
|
|
33191
|
+
const probe_context = document_state.context_tracker ? document_state.context_tracker.get_context_at_position(params.position) : "stata" /* STATA */;
|
|
33192
|
+
const completion_context = detect_completion_context(document_state, params.position, probe_context === "stata" /* STATA */ ? document_state.tokens : undefined);
|
|
32499
33193
|
const is_macro_context = completion_context.type === "macro";
|
|
32500
33194
|
return { isIncomplete: is_macro_context, items };
|
|
32501
33195
|
}
|
|
@@ -32853,6 +33547,7 @@ var import_node7, DEFAULT_SETTINGS, MAX_IHLP_CACHE_SIZE = 500, MAX_RESOLVE_STHLP
|
|
|
32853
33547
|
var init_server_handlers = __esm(() => {
|
|
32854
33548
|
init_completion();
|
|
32855
33549
|
init_context_tracker();
|
|
33550
|
+
init_types2();
|
|
32856
33551
|
init_scope_resolver();
|
|
32857
33552
|
init_include_expander();
|
|
32858
33553
|
init_marker_scanner();
|
|
@@ -32865,7 +33560,7 @@ var init_server_handlers = __esm(() => {
|
|
|
32865
33560
|
severity: {
|
|
32866
33561
|
undefinedMacro: "warning",
|
|
32867
33562
|
undefinedVariable: "off",
|
|
32868
|
-
styleWarnings: "
|
|
33563
|
+
styleWarnings: "information",
|
|
32869
33564
|
malformedOperator: "warning",
|
|
32870
33565
|
spacedCompoundOperator: "information",
|
|
32871
33566
|
invalidOperatorSequence: "error",
|
|
@@ -32906,6 +33601,9 @@ var init_server_handlers = __esm(() => {
|
|
|
32906
33601
|
max_forward_depth: 10,
|
|
32907
33602
|
max_chain_depth: 20,
|
|
32908
33603
|
max_callee_revalidations: 10,
|
|
33604
|
+
max_cached_files: 2000,
|
|
33605
|
+
max_cached_scopes: 1000,
|
|
33606
|
+
max_cached_forward_closures: 2000,
|
|
32909
33607
|
diagnostics: {
|
|
32910
33608
|
missing_file: "warning",
|
|
32911
33609
|
max_depth: "information",
|
|
@@ -33084,6 +33782,15 @@ function validate_comment_formatting_config(config, log_warning) {
|
|
|
33084
33782
|
if (typeof cross_file.max_callee_revalidations === "number" && cross_file.max_callee_revalidations > 0) {
|
|
33085
33783
|
validated_config.cross_file.max_callee_revalidations = cross_file.max_callee_revalidations;
|
|
33086
33784
|
}
|
|
33785
|
+
if (typeof cross_file.max_cached_files === "number" && cross_file.max_cached_files > 0) {
|
|
33786
|
+
validated_config.cross_file.max_cached_files = cross_file.max_cached_files;
|
|
33787
|
+
}
|
|
33788
|
+
if (typeof cross_file.max_cached_scopes === "number" && cross_file.max_cached_scopes > 0) {
|
|
33789
|
+
validated_config.cross_file.max_cached_scopes = cross_file.max_cached_scopes;
|
|
33790
|
+
}
|
|
33791
|
+
if (typeof cross_file.max_cached_forward_closures === "number" && cross_file.max_cached_forward_closures > 0) {
|
|
33792
|
+
validated_config.cross_file.max_cached_forward_closures = cross_file.max_cached_forward_closures;
|
|
33793
|
+
}
|
|
33087
33794
|
if (cross_file.diagnostics) {
|
|
33088
33795
|
const valid_severities = ["error", "warning", "information", "info", "off"];
|
|
33089
33796
|
const valid_case_mismatch_severities = [
|
|
@@ -33766,10 +34473,16 @@ async function build_check_context(workspace_root, config) {
|
|
|
33766
34473
|
}
|
|
33767
34474
|
},
|
|
33768
34475
|
warn: (message) => console.error(message)
|
|
34476
|
+
}, undefined, {
|
|
34477
|
+
max_cached_files: config.cross_file.max_cached_files,
|
|
34478
|
+
max_cached_scopes: config.cross_file.max_cached_scopes
|
|
33769
34479
|
});
|
|
33770
34480
|
const forward_scope_resolver = new ForwardScopeResolver(scope_resolver, {
|
|
33771
34481
|
max_forward_depth: config.cross_file.max_forward_depth
|
|
33772
34482
|
});
|
|
34483
|
+
if (config.cross_file.max_cached_forward_closures !== undefined) {
|
|
34484
|
+
forward_scope_resolver.set_forward_closure_memo_capacity(config.cross_file.max_cached_forward_closures);
|
|
34485
|
+
}
|
|
33773
34486
|
const diagnostics_provider = new DiagnosticsProvider({
|
|
33774
34487
|
sendDiagnostics: () => {
|
|
33775
34488
|
return;
|
|
@@ -34235,57 +34948,6 @@ var init_main = __esm(() => {
|
|
|
34235
34948
|
})(TextDocument || (TextDocument = {}));
|
|
34236
34949
|
});
|
|
34237
34950
|
|
|
34238
|
-
// src/utils/token-utils.ts
|
|
34239
|
-
function position_before2(a, b) {
|
|
34240
|
-
return a.line < b.line || a.line === b.line && a.character < b.character;
|
|
34241
|
-
}
|
|
34242
|
-
function position_at_or_before(a, b) {
|
|
34243
|
-
return a.line < b.line || a.line === b.line && a.character <= b.character;
|
|
34244
|
-
}
|
|
34245
|
-
function find_last_token_starting_at_or_before(tokens, position) {
|
|
34246
|
-
let low = 0;
|
|
34247
|
-
let high = tokens.length - 1;
|
|
34248
|
-
let best = -1;
|
|
34249
|
-
while (low <= high) {
|
|
34250
|
-
const mid = low + high >>> 1;
|
|
34251
|
-
const start = tokens[mid].range.start;
|
|
34252
|
-
if (position_at_or_before(start, position)) {
|
|
34253
|
-
best = mid;
|
|
34254
|
-
low = mid + 1;
|
|
34255
|
-
} else {
|
|
34256
|
-
high = mid - 1;
|
|
34257
|
-
}
|
|
34258
|
-
}
|
|
34259
|
-
return best;
|
|
34260
|
-
}
|
|
34261
|
-
function find_last_token_starting_before(tokens, position) {
|
|
34262
|
-
let low = 0;
|
|
34263
|
-
let high = tokens.length - 1;
|
|
34264
|
-
let best = -1;
|
|
34265
|
-
while (low <= high) {
|
|
34266
|
-
const mid = low + high >>> 1;
|
|
34267
|
-
const start = tokens[mid].range.start;
|
|
34268
|
-
if (position_before2(start, position)) {
|
|
34269
|
-
best = mid;
|
|
34270
|
-
low = mid + 1;
|
|
34271
|
-
} else {
|
|
34272
|
-
high = mid - 1;
|
|
34273
|
-
}
|
|
34274
|
-
}
|
|
34275
|
-
return best;
|
|
34276
|
-
}
|
|
34277
|
-
function find_token_index_at_position(tokens, position) {
|
|
34278
|
-
const candidate = find_last_token_starting_at_or_before(tokens, position);
|
|
34279
|
-
if (candidate === -1) {
|
|
34280
|
-
return -1;
|
|
34281
|
-
}
|
|
34282
|
-
const end = tokens[candidate].range.end;
|
|
34283
|
-
if (position_before2(position, end)) {
|
|
34284
|
-
return candidate;
|
|
34285
|
-
}
|
|
34286
|
-
return -1;
|
|
34287
|
-
}
|
|
34288
|
-
|
|
34289
34951
|
// src/utils/string-literal-utils.ts
|
|
34290
34952
|
function is_cursor_in_string_literal(document, position) {
|
|
34291
34953
|
if (!document.tokens || document.tokens.length === 0) {
|
|
@@ -38481,27 +39143,20 @@ class IndentationAnalyzer {
|
|
|
38481
39143
|
if (!this.has_trivia(node))
|
|
38482
39144
|
return;
|
|
38483
39145
|
const node_with_trivia = node;
|
|
38484
|
-
|
|
38485
|
-
|
|
38486
|
-
|
|
38487
|
-
|
|
38488
|
-
|
|
38489
|
-
|
|
38490
|
-
|
|
38491
|
-
|
|
38492
|
-
|
|
38493
|
-
|
|
38494
|
-
|
|
38495
|
-
|
|
38496
|
-
|
|
38497
|
-
|
|
38498
|
-
const trivia_line = my_trivia.range.start.line;
|
|
38499
|
-
if (!this.indentation_map.has(trivia_line)) {
|
|
38500
|
-
const { delta, original_indent } = this.calculate_indent_delta(trivia_line, this.current_depth);
|
|
38501
|
-
this.set_indentation(trivia_line, this.current_depth, false, false, false, false, delta, original_indent);
|
|
38502
|
-
}
|
|
38503
|
-
}
|
|
38504
|
-
}
|
|
39146
|
+
this.mark_comment_trivia_indentation(node_with_trivia.leadingTrivia);
|
|
39147
|
+
this.mark_comment_trivia_indentation(node_with_trivia.trailingTrivia);
|
|
39148
|
+
}
|
|
39149
|
+
mark_comment_trivia_indentation(the_trivia) {
|
|
39150
|
+
if (!the_trivia)
|
|
39151
|
+
return;
|
|
39152
|
+
for (const my_trivia of the_trivia) {
|
|
39153
|
+
if (my_trivia.type !== "comment")
|
|
39154
|
+
continue;
|
|
39155
|
+
const trivia_line = my_trivia.range.start.line;
|
|
39156
|
+
if (this.indentation_map.has(trivia_line))
|
|
39157
|
+
continue;
|
|
39158
|
+
const { delta, original_indent } = this.calculate_indent_delta(trivia_line, this.current_depth);
|
|
39159
|
+
this.set_indentation(trivia_line, this.current_depth, false, false, false, false, delta, original_indent);
|
|
38505
39160
|
}
|
|
38506
39161
|
}
|
|
38507
39162
|
is_block_node(node) {
|
|
@@ -38524,6 +39179,7 @@ class IndentationAnalyzer {
|
|
|
38524
39179
|
this.walk_node(my_child);
|
|
38525
39180
|
}
|
|
38526
39181
|
}
|
|
39182
|
+
this.process_block_ending_trivia(node);
|
|
38527
39183
|
this.current_depth--;
|
|
38528
39184
|
if (end_line !== start_line) {
|
|
38529
39185
|
const end_delta_info = this.calculate_indent_delta(end_line, this.current_depth);
|
|
@@ -38556,6 +39212,7 @@ class IndentationAnalyzer {
|
|
|
38556
39212
|
this.set_indentation(line, this.current_depth, false, false, false, false, delta, original_indent);
|
|
38557
39213
|
}
|
|
38558
39214
|
}
|
|
39215
|
+
this.process_block_ending_trivia(node);
|
|
38559
39216
|
this.current_depth--;
|
|
38560
39217
|
if (end_line !== start_line) {
|
|
38561
39218
|
const end_delta_info = this.calculate_indent_delta(end_line, this.current_depth);
|
|
@@ -38567,6 +39224,10 @@ class IndentationAnalyzer {
|
|
|
38567
39224
|
const { delta, original_indent } = this.calculate_indent_delta(start_line, this.current_depth);
|
|
38568
39225
|
this.set_indentation(start_line, this.current_depth, false, false, false, false, delta, original_indent);
|
|
38569
39226
|
}
|
|
39227
|
+
process_block_ending_trivia(node) {
|
|
39228
|
+
const node_with_trivia = node;
|
|
39229
|
+
this.mark_comment_trivia_indentation(node_with_trivia.blockEndingTrivia);
|
|
39230
|
+
}
|
|
38570
39231
|
process_continuations(tokens) {
|
|
38571
39232
|
let continuation_indent = 0;
|
|
38572
39233
|
let in_continuation = false;
|
|
@@ -40070,6 +40731,7 @@ class PrettyPrinter {
|
|
|
40070
40731
|
for (const my_stmt of node.body) {
|
|
40071
40732
|
the_parts.push(this.printNode(my_stmt));
|
|
40072
40733
|
}
|
|
40734
|
+
the_parts.push(this.printBlockEndingTrivia(node));
|
|
40073
40735
|
this.current_indent--;
|
|
40074
40736
|
the_parts.push(`${this.getIndent()}}`);
|
|
40075
40737
|
}
|
|
@@ -40090,7 +40752,9 @@ class PrettyPrinter {
|
|
|
40090
40752
|
printOption(option) {
|
|
40091
40753
|
let result = option.name;
|
|
40092
40754
|
if (option.argument !== undefined) {
|
|
40093
|
-
|
|
40755
|
+
const close_paren = option.argument_unclosed ? "" : ")";
|
|
40756
|
+
const argument = format_expression_spacing(option.argument);
|
|
40757
|
+
result += `(${argument}${close_paren}`;
|
|
40094
40758
|
}
|
|
40095
40759
|
return result;
|
|
40096
40760
|
}
|
|
@@ -40102,6 +40766,7 @@ class PrettyPrinter {
|
|
|
40102
40766
|
for (const my_stmt of node.body) {
|
|
40103
40767
|
the_lines.push(this.printNode(my_stmt));
|
|
40104
40768
|
}
|
|
40769
|
+
the_lines.push(this.printBlockEndingTrivia(node));
|
|
40105
40770
|
this.current_indent--;
|
|
40106
40771
|
the_lines.push(`${this.getIndent()}end`);
|
|
40107
40772
|
return the_lines.join("");
|
|
@@ -40160,6 +40825,7 @@ class PrettyPrinter {
|
|
|
40160
40825
|
for (const my_stmt of node.body) {
|
|
40161
40826
|
the_lines.push(this.printNode(my_stmt));
|
|
40162
40827
|
}
|
|
40828
|
+
the_lines.push(this.printBlockEndingTrivia(node));
|
|
40163
40829
|
this.current_indent--;
|
|
40164
40830
|
the_lines.push(`${this.getIndent()}}`);
|
|
40165
40831
|
return the_lines.join("");
|
|
@@ -40220,6 +40886,19 @@ class PrettyPrinter {
|
|
|
40220
40886
|
}
|
|
40221
40887
|
return the_parts.join("");
|
|
40222
40888
|
}
|
|
40889
|
+
printBlockEndingTrivia(node) {
|
|
40890
|
+
if (!node.blockEndingTrivia || node.blockEndingTrivia.length === 0) {
|
|
40891
|
+
return "";
|
|
40892
|
+
}
|
|
40893
|
+
const the_parts = [];
|
|
40894
|
+
for (const my_trivia of node.blockEndingTrivia) {
|
|
40895
|
+
the_parts.push(this.getIndent());
|
|
40896
|
+
the_parts.push(this.printTrivia(my_trivia));
|
|
40897
|
+
the_parts.push(`
|
|
40898
|
+
`);
|
|
40899
|
+
}
|
|
40900
|
+
return the_parts.join("");
|
|
40901
|
+
}
|
|
40223
40902
|
printTrivia(trivia) {
|
|
40224
40903
|
return trivia.content;
|
|
40225
40904
|
}
|
|
@@ -40315,28 +40994,17 @@ class CodeFormatter {
|
|
|
40315
40994
|
const the_embedded_blocks = new Map;
|
|
40316
40995
|
let my_placeholder_counter = 0;
|
|
40317
40996
|
let my_modified_content = document.content;
|
|
40318
|
-
const
|
|
40319
|
-
for (const
|
|
40997
|
+
const the_replacement_units = this.coalesce_embedded_ranges(the_doc, context_ranges);
|
|
40998
|
+
for (const my_unit of the_replacement_units) {
|
|
40320
40999
|
if (my_placeholder_counter >= MAX_EMBEDDED_BLOCKS) {
|
|
40321
41000
|
break;
|
|
40322
41001
|
}
|
|
40323
41002
|
const my_placeholder = `__EMBEDDED_BLOCK_${my_placeholder_counter}__`;
|
|
40324
41003
|
the_embedded_blocks.set(my_placeholder, {
|
|
40325
|
-
content:
|
|
40326
|
-
range:
|
|
41004
|
+
content: my_unit.content,
|
|
41005
|
+
range: my_unit.range
|
|
40327
41006
|
});
|
|
40328
|
-
|
|
40329
|
-
if (my_range.is_single_line) {
|
|
40330
|
-
actual_range = my_range.range;
|
|
40331
|
-
} else {
|
|
40332
|
-
const actual_end_line = my_range.end_delimiter ? my_range.end_delimiter.range.start.line : my_range.range.end.line;
|
|
40333
|
-
const end_line_text = get_line_text(the_doc, actual_end_line);
|
|
40334
|
-
actual_range = {
|
|
40335
|
-
start: my_range.range.start,
|
|
40336
|
-
end: { line: actual_end_line, character: end_line_text.length }
|
|
40337
|
-
};
|
|
40338
|
-
}
|
|
40339
|
-
my_modified_content = this.replace_range_in_content(my_modified_content, actual_range, my_placeholder);
|
|
41007
|
+
my_modified_content = this.replace_range_in_content(my_modified_content, my_unit.actual_range, my_placeholder);
|
|
40340
41008
|
my_placeholder_counter++;
|
|
40341
41009
|
}
|
|
40342
41010
|
const indent_size = options.tabSize ?? server_config?.formatting?.indentSize ?? 4;
|
|
@@ -40366,7 +41034,7 @@ class CodeFormatter {
|
|
|
40366
41034
|
const indented_block_lines = block_lines.map((line, index) => {
|
|
40367
41035
|
if (index === 0) {
|
|
40368
41036
|
return leading_indent + line;
|
|
40369
|
-
} else if (index === block_lines.length - 1 && line.trim() === expected_end_delimiter) {
|
|
41037
|
+
} else if (!my_block_info.range.is_single_line && index === block_lines.length - 1 && line.trim() === expected_end_delimiter) {
|
|
40370
41038
|
return leading_indent + line;
|
|
40371
41039
|
} else {
|
|
40372
41040
|
return line;
|
|
@@ -40391,6 +41059,90 @@ class CodeFormatter {
|
|
|
40391
41059
|
newText: this.strip_trailing_whitespace(my_formatted_content)
|
|
40392
41060
|
}];
|
|
40393
41061
|
}
|
|
41062
|
+
embedded_range_span(doc, context_range) {
|
|
41063
|
+
if (context_range.is_single_line) {
|
|
41064
|
+
return {
|
|
41065
|
+
start_line: context_range.range.start.line,
|
|
41066
|
+
end_line: context_range.range.end.line
|
|
41067
|
+
};
|
|
41068
|
+
}
|
|
41069
|
+
const my_end_line = context_range.end_delimiter ? context_range.end_delimiter.range.start.line : context_range.range.end.line;
|
|
41070
|
+
return { start_line: context_range.range.start.line, end_line: my_end_line };
|
|
41071
|
+
}
|
|
41072
|
+
coalesce_embedded_ranges(doc, context_ranges) {
|
|
41073
|
+
const the_spans = context_ranges.map((my_range) => ({
|
|
41074
|
+
my_range,
|
|
41075
|
+
span: this.embedded_range_span(doc, my_range)
|
|
41076
|
+
})).sort((a, b) => {
|
|
41077
|
+
if (a.span.start_line !== b.span.start_line) {
|
|
41078
|
+
return a.span.start_line - b.span.start_line;
|
|
41079
|
+
}
|
|
41080
|
+
return a.span.end_line - b.span.end_line;
|
|
41081
|
+
});
|
|
41082
|
+
const the_groups = [];
|
|
41083
|
+
for (const my_item of the_spans) {
|
|
41084
|
+
const my_last = the_groups[the_groups.length - 1];
|
|
41085
|
+
if (my_last && my_item.span.start_line <= my_last.end_line) {
|
|
41086
|
+
my_last.end_line = Math.max(my_last.end_line, my_item.span.end_line);
|
|
41087
|
+
my_last.members.push(my_item.my_range);
|
|
41088
|
+
} else {
|
|
41089
|
+
the_groups.push({
|
|
41090
|
+
start_line: my_item.span.start_line,
|
|
41091
|
+
end_line: my_item.span.end_line,
|
|
41092
|
+
members: [my_item.my_range]
|
|
41093
|
+
});
|
|
41094
|
+
}
|
|
41095
|
+
}
|
|
41096
|
+
const the_line_count = get_line_count(doc);
|
|
41097
|
+
const the_units = [];
|
|
41098
|
+
for (const my_group of the_groups) {
|
|
41099
|
+
if (my_group.members.length === 1) {
|
|
41100
|
+
const my_range = my_group.members[0];
|
|
41101
|
+
const my_end_line_text2 = get_line_text(doc, my_group.end_line);
|
|
41102
|
+
the_units.push({
|
|
41103
|
+
content: this.extract_block_content(doc, my_range),
|
|
41104
|
+
range: my_range,
|
|
41105
|
+
actual_range: {
|
|
41106
|
+
start: { line: my_group.start_line, character: 0 },
|
|
41107
|
+
end: {
|
|
41108
|
+
line: my_group.end_line,
|
|
41109
|
+
character: my_end_line_text2.length
|
|
41110
|
+
}
|
|
41111
|
+
}
|
|
41112
|
+
});
|
|
41113
|
+
continue;
|
|
41114
|
+
}
|
|
41115
|
+
const my_lines = [];
|
|
41116
|
+
for (let my_line = my_group.start_line;my_line <= my_group.end_line && my_line < the_line_count; my_line++) {
|
|
41117
|
+
const my_text = get_line_text(doc, my_line);
|
|
41118
|
+
my_lines.push(my_line === my_group.start_line ? my_text.trimStart() : my_text);
|
|
41119
|
+
}
|
|
41120
|
+
const my_end_line_text = get_line_text(doc, my_group.end_line);
|
|
41121
|
+
const my_synthetic_range = {
|
|
41122
|
+
context: my_group.members[0].context,
|
|
41123
|
+
range: {
|
|
41124
|
+
start: { line: my_group.start_line, character: 0 },
|
|
41125
|
+
end: { line: my_group.end_line, character: Number.MAX_SAFE_INTEGER }
|
|
41126
|
+
},
|
|
41127
|
+
start_delimiter: my_group.members[0].start_delimiter,
|
|
41128
|
+
is_single_line: true
|
|
41129
|
+
};
|
|
41130
|
+
the_units.push({
|
|
41131
|
+
content: my_lines.join(`
|
|
41132
|
+
`),
|
|
41133
|
+
range: my_synthetic_range,
|
|
41134
|
+
actual_range: {
|
|
41135
|
+
start: { line: my_group.start_line, character: 0 },
|
|
41136
|
+
end: {
|
|
41137
|
+
line: my_group.end_line,
|
|
41138
|
+
character: my_end_line_text.length
|
|
41139
|
+
}
|
|
41140
|
+
}
|
|
41141
|
+
});
|
|
41142
|
+
}
|
|
41143
|
+
the_units.sort((a, b) => b.actual_range.start.line - a.actual_range.start.line);
|
|
41144
|
+
return the_units;
|
|
41145
|
+
}
|
|
40394
41146
|
extract_block_content(doc, context_range) {
|
|
40395
41147
|
const the_start_line = context_range.range.start.line;
|
|
40396
41148
|
const the_end_line = context_range.end_delimiter ? context_range.end_delimiter.range.start.line : context_range.range.end.line;
|
|
@@ -71745,6 +72497,13 @@ async function create_server(options) {
|
|
|
71745
72497
|
function configure_completion_provider(settings) {
|
|
71746
72498
|
completion_provider?.configure_completion(settings.completion);
|
|
71747
72499
|
}
|
|
72500
|
+
function apply_cache_capacities(settings) {
|
|
72501
|
+
scope_resolver?.set_cache_capacities({
|
|
72502
|
+
max_cached_files: settings.cross_file?.max_cached_files ?? DEFAULT_SETTINGS.cross_file.max_cached_files,
|
|
72503
|
+
max_cached_scopes: settings.cross_file?.max_cached_scopes ?? DEFAULT_SETTINGS.cross_file.max_cached_scopes
|
|
72504
|
+
});
|
|
72505
|
+
forward_scope_resolver?.set_forward_closure_memo_capacity(settings.cross_file?.max_cached_forward_closures ?? DEFAULT_SETTINGS.cross_file.max_cached_forward_closures ?? 2000);
|
|
72506
|
+
}
|
|
71748
72507
|
function reset_workspace_indexing_state() {
|
|
71749
72508
|
workspace_indexer?.reset();
|
|
71750
72509
|
dependency_graph?.reset();
|
|
@@ -71757,6 +72516,7 @@ async function create_server(options) {
|
|
|
71757
72516
|
}
|
|
71758
72517
|
last_applied_indexing_signature = indexing_affecting_signature(settings);
|
|
71759
72518
|
configure_completion_provider(settings);
|
|
72519
|
+
apply_cache_capacities(settings);
|
|
71760
72520
|
if (workspace_indexer) {
|
|
71761
72521
|
workspace_indexer.configure(settings);
|
|
71762
72522
|
workspace_indexer.set_max_indexed_files(settings.cross_file?.max_indexed_files ?? 1000);
|
|
@@ -71810,6 +72570,7 @@ async function create_server(options) {
|
|
|
71810
72570
|
configure_workspace_indexing(settings, active_workspace_roots, true);
|
|
71811
72571
|
} else {
|
|
71812
72572
|
configure_completion_provider(settings);
|
|
72573
|
+
apply_cache_capacities(settings);
|
|
71813
72574
|
workspace_indexer?.configure(settings);
|
|
71814
72575
|
revalidate_all_open_docs();
|
|
71815
72576
|
}
|
|
@@ -72125,6 +72886,7 @@ ${scope_resolver.get_reverse_deps_debug_info()}`);
|
|
|
72125
72886
|
configure_workspace_indexing(settings, active_workspace_roots, true);
|
|
72126
72887
|
} else {
|
|
72127
72888
|
configure_completion_provider(settings);
|
|
72889
|
+
apply_cache_capacities(settings);
|
|
72128
72890
|
workspace_indexer?.configure(settings);
|
|
72129
72891
|
revalidate_all_open_docs();
|
|
72130
72892
|
}
|
|
@@ -72472,4 +73234,4 @@ export {
|
|
|
72472
73234
|
is_cli_entry_point
|
|
72473
73235
|
};
|
|
72474
73236
|
|
|
72475
|
-
//# debugId=
|
|
73237
|
+
//# debugId=DFA4590C23722F1564756E2164756E21
|