@jbearak/sight 0.14.5 → 0.15.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.
@@ -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.14.5",
55
+ version: "0.15.0",
56
56
  type: "module",
57
57
  workspaces: [
58
58
  "client"
@@ -115,6 +115,7 @@ var init_package = __esm(() => {
115
115
  license: "GPL-3.0",
116
116
  dependencies: {
117
117
  "@jbearak/dta-parser": "^0.6.0",
118
+ ignore: "7.0.5",
118
119
  picomatch: "^4.0.2",
119
120
  "smol-toml": "^1.6.1",
120
121
  "vscode-languageserver": "^9.0.1",
@@ -917,7 +918,10 @@ function map_public_config_to_partial_config(raw, warn) {
917
918
  }
918
919
  const workspace = object_value(raw, "workspace", "workspace", warn);
919
920
  if (workspace) {
920
- warn_unknown_keys(workspace, ["exclude"], "workspace", warn);
921
+ warn_unknown_keys(workspace, ["exclude", "respectGitignore"], "workspace", warn);
922
+ const mapped_workspace = {};
923
+ assign_boolean(mapped_workspace, "respectGitignore", workspace, "respectGitignore", "workspace.respectGitignore", warn);
924
+ maybe_assign_object(root, "workspace", mapped_workspace);
921
925
  }
922
926
  const canonical_exclude = workspace ? pick_key(workspace, "exclude", warn, "workspace.exclude") : undefined;
923
927
  const legacy_exclude = pick_key(raw, "exclude", warn, "exclude");
@@ -13310,6 +13314,8 @@ var init_parser = __esm(() => {
13310
13314
  pending_trivia = [];
13311
13315
  context_tracker = null;
13312
13316
  inside_program = false;
13317
+ if_brace_scan_end = -1;
13318
+ if_brace_scan_result = false;
13313
13319
  static OPENING_DELIMITER_PATTERN = /^(`")+$/;
13314
13320
  static CLOSING_DELIMITER_PATTERN = /^("')+$/;
13315
13321
  parse(tokens, context_tracker) {
@@ -13317,6 +13323,8 @@ var init_parser = __esm(() => {
13317
13323
  this.current = 0;
13318
13324
  this.errors = [];
13319
13325
  this.pending_trivia = [];
13326
+ this.if_brace_scan_end = -1;
13327
+ this.if_brace_scan_result = false;
13320
13328
  this.context_tracker = context_tracker || null;
13321
13329
  const nodes = [];
13322
13330
  while (!this.isAtEnd()) {
@@ -13346,7 +13354,7 @@ var init_parser = __esm(() => {
13346
13354
  errors: this.errors
13347
13355
  };
13348
13356
  }
13349
- parseStatement() {
13357
+ parseStatement(consume_terminator = true) {
13350
13358
  const leading_trivia = [...this.pending_trivia, ...this.collectTrivia()];
13351
13359
  this.pending_trivia = [];
13352
13360
  if (this.isAtEnd()) {
@@ -13433,7 +13441,7 @@ var init_parser = __esm(() => {
13433
13441
  if (node && this.isNodeWithTrivia(node) && trailing_trivia.length > 0) {
13434
13442
  node.trailingTrivia = trailing_trivia;
13435
13443
  }
13436
- if (this.check("STATEMENT_TERMINATOR")) {
13444
+ if (consume_terminator && this.check("STATEMENT_TERMINATOR")) {
13437
13445
  this.advance();
13438
13446
  }
13439
13447
  return node;
@@ -14650,13 +14658,31 @@ var init_parser = __esm(() => {
14650
14658
  }
14651
14659
  return false;
14652
14660
  }
14661
+ hasIfBrace() {
14662
+ if (this.current <= this.if_brace_scan_end) {
14663
+ return this.if_brace_scan_result;
14664
+ }
14665
+ for (let i = this.current;i < this.tokens.length; i++) {
14666
+ const token = this.tokens[i];
14667
+ if (token.type === "LBRACE" || token.type === "EOF" || token.type === "STATEMENT_TERMINATOR" && !is_swallowed_continuation_terminator(token, this.tokens[i - 1]?.type === "CONTINUATION")) {
14668
+ this.if_brace_scan_end = i;
14669
+ this.if_brace_scan_result = token.type === "LBRACE";
14670
+ return this.if_brace_scan_result;
14671
+ }
14672
+ }
14673
+ return false;
14674
+ }
14653
14675
  parseIfStatement() {
14654
14676
  const ifToken = this.advance();
14677
+ const has_brace = this.hasIfBrace();
14655
14678
  const condition_tokens = [];
14656
14679
  const preceded_by_continuation = [];
14657
14680
  const continuation = new ContinuationTracker;
14658
14681
  const condition_start_line = ifToken.range.start.line;
14659
14682
  let paren_depth = 0;
14683
+ let bracket_depth = 0;
14684
+ let previous_operand;
14685
+ let is_single_statement = false;
14660
14686
  while (!this.check("LBRACE") && !this.isAtEnd()) {
14661
14687
  if (this.check("CONTINUATION")) {
14662
14688
  const cont_token = this.peek();
@@ -14668,7 +14694,15 @@ var init_parser = __esm(() => {
14668
14694
  if (this.check("STATEMENT_TERMINATOR")) {
14669
14695
  break;
14670
14696
  }
14671
- const token = this.advance();
14697
+ const token = this.peek();
14698
+ const follows_continuation = continuation.collect(token);
14699
+ const joins_operand = previous_operand && previous_operand.type !== "RPAREN" && previous_operand.type !== "RBRACKET" && (this.isAdjacentToken(previous_operand, token) || follows_continuation && token.range.start.character === 0);
14700
+ const starts_nested_if = this.checkWord("if");
14701
+ if ((!has_brace || starts_nested_if) && paren_depth === 0 && bracket_depth === 0 && previous_operand && !joins_operand && (token.type === "WORD" || this.isMacroRefToken(token) || token.type === "MATA_INLINE" || token.type === "PYTHON_INLINE")) {
14702
+ is_single_statement = true;
14703
+ break;
14704
+ }
14705
+ this.advance();
14672
14706
  if (token.type === "LPAREN") {
14673
14707
  paren_depth++;
14674
14708
  } else if (token.type === "RPAREN") {
@@ -14678,8 +14712,16 @@ var init_parser = __esm(() => {
14678
14712
  paren_depth = 0;
14679
14713
  }
14680
14714
  }
14715
+ if (token.type === "LBRACKET") {
14716
+ bracket_depth++;
14717
+ } else if (token.type === "RBRACKET") {
14718
+ bracket_depth = Math.max(0, bracket_depth - 1);
14719
+ }
14720
+ if (token.type !== "COMMENT_LINE" && token.type !== "COMMENT_BLOCK") {
14721
+ previous_operand = token.type === "WORD" || token.type === "NUMBER" || token.type === "STRING" || this.isMacroRefToken(token) || token.type === "RPAREN" || token.type === "RBRACKET" ? token : undefined;
14722
+ }
14681
14723
  condition_tokens.push(token);
14682
- preceded_by_continuation.push(continuation.collect(token));
14724
+ preceded_by_continuation.push(follows_continuation);
14683
14725
  }
14684
14726
  const condition = this.reconstruct_value_tokens(condition_tokens, preceded_by_continuation).trim();
14685
14727
  if (paren_depth > 0) {
@@ -14690,7 +14732,11 @@ var init_parser = __esm(() => {
14690
14732
  }
14691
14733
  const body = [];
14692
14734
  let blockEndingTrivia;
14693
- if (this.check("LBRACE")) {
14735
+ if (is_single_statement) {
14736
+ const statement = this.parseStatement(false);
14737
+ if (statement)
14738
+ body.push(statement);
14739
+ } else if (this.check("LBRACE")) {
14694
14740
  const lbrace_index = this.current;
14695
14741
  const lbrace_token = this.advance();
14696
14742
  const has_condition_before = lbrace_token.range.start.line === condition_start_line;
@@ -14708,9 +14754,10 @@ var init_parser = __esm(() => {
14708
14754
  }
14709
14755
  return {
14710
14756
  type: "if",
14757
+ ...is_single_statement ? { is_single_statement: true } : {},
14711
14758
  condition: condition.trim(),
14712
14759
  body,
14713
- range: this.makeRange(ifToken.range.start, this.previous().range.end),
14760
+ range: this.makeRange(ifToken.range.start, is_single_statement && body.length > 0 ? body[body.length - 1].range.end : this.previous().range.end),
14714
14761
  blockEndingTrivia
14715
14762
  };
14716
14763
  }
@@ -20742,6 +20789,61 @@ async function with_parse_timeout(operation, timeout_ms = PARSE_TIMEOUT_MS) {
20742
20789
  }
20743
20790
  var PARSE_TIMEOUT_MS = 5000;
20744
20791
 
20792
+ // src/source-analysis/index.ts
20793
+ import * as path4 from "path";
20794
+ function analyze_source(content, uri) {
20795
+ const lexer = new StataLexer;
20796
+ const parser = new StataParser;
20797
+ const analyzer = new SemanticAnalyzer;
20798
+ const directive_parser = new DirectiveParser;
20799
+ const lex_result = lexer.tokenize(content);
20800
+ const directive_result = directive_parser.parse(content, uri, lex_result.tokens);
20801
+ const parse_result = parser.parse(lex_result.tokens);
20802
+ const analysis = analyzer.analyze(parse_result.ast, uri, undefined, undefined, lex_result.tokens);
20803
+ return {
20804
+ tokens: lex_result.tokens,
20805
+ analysis,
20806
+ directives: directive_result
20807
+ };
20808
+ }
20809
+ function prepare_forward_calls(options) {
20810
+ let command_calls = options.command_calls;
20811
+ try {
20812
+ const caller_dir = path4.dirname(URI.parse(options.uri).fsPath);
20813
+ const { timeline } = build_cd_timeline({
20814
+ starting_wd: options.working_directory,
20815
+ caller_dir,
20816
+ cd_commands: options.cd_commands,
20817
+ workspace_roots: options.workspace_roots,
20818
+ fs: options.fs
20819
+ });
20820
+ command_calls = apply_cd_timeline(command_calls, timeline);
20821
+ } catch (error) {
20822
+ if (!options.recover_command_projection) {
20823
+ throw error;
20824
+ }
20825
+ }
20826
+ const directive_calls = options.directive_calls.map((my_directive) => ({
20827
+ type: my_directive.type,
20828
+ raw_path: my_directive.raw_path,
20829
+ call_site_line: my_directive.call_site_line,
20830
+ range: my_directive.range,
20831
+ source: "directive",
20832
+ is_static: true,
20833
+ caller_uri: options.uri,
20834
+ working_directory: options.working_directory
20835
+ }));
20836
+ return [...command_calls, ...directive_calls];
20837
+ }
20838
+ var init_source_analysis = __esm(() => {
20839
+ init_esm();
20840
+ init_analyzer();
20841
+ init_directive_parser();
20842
+ init_lexer();
20843
+ init_parser();
20844
+ init_file_path_utils();
20845
+ });
20846
+
20745
20847
  // src/utils/polling-cancellation-token.ts
20746
20848
  function polling_cancellation_token(should_continue, parent) {
20747
20849
  return {
@@ -20757,7 +20859,6 @@ var no_op_cancellation_event = () => ({ dispose: () => {
20757
20859
 
20758
20860
  // src/document-store.ts
20759
20861
  import * as fs4 from "fs";
20760
- import * as path4 from "path";
20761
20862
 
20762
20863
  class DocumentStore {
20763
20864
  documents = new Map;
@@ -21156,17 +21257,16 @@ class DocumentStore {
21156
21257
  const directive_parser = new DirectiveParser;
21157
21258
  let resolved_working_directory;
21158
21259
  let staged_effects;
21260
+ let parsed_directives;
21159
21261
  try {
21160
21262
  const directive_result = directive_parser.parse(content, uri, lex_result.result.tokens);
21263
+ parsed_directives = directive_result;
21161
21264
  staged_effects = this.stage_cross_file_effects(directive_result, effective_scope_resolver_config);
21162
21265
  if (directive_result.working_directory) {
21163
21266
  resolved_working_directory = this.resolve_working_directory(directive_result.working_directory, uri);
21164
21267
  } else if (this.scope_resolver) {
21165
21268
  try {
21166
- const scope_result = await this.scope_resolver.resolve(uri, content, effective_scope_resolver_config, cancellation_token, { register_dependencies: false });
21167
- if (scope_result.inherited_working_directory) {
21168
- resolved_working_directory = scope_result.inherited_working_directory;
21169
- }
21269
+ resolved_working_directory = await this.scope_resolver.resolve_document_working_directory(uri, directive_result, effective_scope_resolver_config, cancellation_token);
21170
21270
  } catch {}
21171
21271
  }
21172
21272
  } catch {}
@@ -21220,36 +21320,19 @@ class DocumentStore {
21220
21320
  };
21221
21321
  }
21222
21322
  const diagnostics = this.build_diagnostics(lex_result.result.errors, parse_result.result.errors, analyze_result.result.diagnostics);
21223
- let restamped_command_calls = analyze_result.result.forward_calls;
21323
+ let the_forward_directives = [];
21224
21324
  try {
21225
- const my_caller_dir = path4.dirname(URI.parse(uri).fsPath);
21226
- const { timeline: cd_timeline } = build_cd_timeline({
21227
- starting_wd: resolved_working_directory,
21228
- caller_dir: my_caller_dir,
21229
- cd_commands: analyze_result.result.cd_commands,
21230
- workspace_roots: this.workspace_roots
21231
- });
21232
- restamped_command_calls = apply_cd_timeline(analyze_result.result.forward_calls, cd_timeline);
21233
- } catch {}
21234
- let all_forward_calls = restamped_command_calls;
21235
- try {
21236
- const directive_parser2 = new DirectiveParser;
21237
- const directive_result = directive_parser2.parse_forward_call_directives(content, uri, lex_result.result.tokens);
21238
- const directive_forward_calls = directive_result.forward_calls.map((d) => ({
21239
- type: d.type,
21240
- raw_path: d.raw_path,
21241
- call_site_line: d.call_site_line,
21242
- range: d.range,
21243
- source: "directive",
21244
- is_static: true,
21245
- caller_uri: uri,
21246
- working_directory: resolved_working_directory
21247
- }));
21248
- all_forward_calls = [
21249
- ...restamped_command_calls,
21250
- ...directive_forward_calls
21251
- ];
21325
+ the_forward_directives = parsed_directives ? parsed_directives.forward_calls ?? [] : directive_parser.parse_forward_call_directives(content, uri, lex_result.result.tokens).forward_calls;
21252
21326
  } catch {}
21327
+ const all_forward_calls = prepare_forward_calls({
21328
+ uri,
21329
+ command_calls: analyze_result.result.forward_calls,
21330
+ directive_calls: the_forward_directives,
21331
+ cd_commands: analyze_result.result.cd_commands,
21332
+ working_directory: resolved_working_directory,
21333
+ workspace_roots: this.workspace_roots,
21334
+ recover_command_projection: true
21335
+ });
21253
21336
  return {
21254
21337
  state: {
21255
21338
  uri,
@@ -21415,8 +21498,7 @@ var init_document_store = __esm(() => {
21415
21498
  init_context_tracker();
21416
21499
  init_directive_parser();
21417
21500
  init_workspace_roots();
21418
- init_file_path_utils();
21419
- init_esm();
21501
+ init_source_analysis();
21420
21502
  import_vscode_languageserver = __toESM(require_main4(), 1);
21421
21503
  });
21422
21504
 
@@ -22665,9 +22747,6 @@ function scope_resolver_config_for(config) {
22665
22747
 
22666
22748
  class ScopeResolver {
22667
22749
  directive_parser;
22668
- lexer;
22669
- parser;
22670
- analyzer;
22671
22750
  file_cache;
22672
22751
  scope_cache;
22673
22752
  uri_to_cache_keys;
@@ -22682,9 +22761,6 @@ class ScopeResolver {
22682
22761
  resolve_fs;
22683
22762
  constructor(logger2, content_provider, cache_capacities) {
22684
22763
  this.directive_parser = new DirectiveParser;
22685
- this.lexer = new StataLexer;
22686
- this.parser = new StataParser;
22687
- this.analyzer = new SemanticAnalyzer;
22688
22764
  this.file_cache = new BoundedLruMap(cache_capacities?.max_cached_files ?? DEFAULT_MAX_CACHED_FILES, {
22689
22765
  on_evict: (_key, entry) => {
22690
22766
  this.cache_metrics.file.evictions++;
@@ -23364,6 +23440,16 @@ class ScopeResolver {
23364
23440
  };
23365
23441
  return this.discover_working_directory(the_backward_directives, new Set, 0, my_config, new Map, current_uri, undefined, true);
23366
23442
  }
23443
+ async resolve_document_working_directory(file_uri, directive_result, config = {}, token) {
23444
+ if (token?.isCancellationRequested || directive_result.working_directory) {
23445
+ return;
23446
+ }
23447
+ const my_config = { ...DEFAULT_CONFIG2, ...config };
23448
+ const { directives: effective_directives } = this.get_effective_backward_directives(file_uri, directive_result.directives, my_config, directive_result.standalone !== undefined);
23449
+ const normalized_directives = this.normalize_directives(effective_directives, []);
23450
+ const working_directory = await this.discover_working_directory(normalized_directives, new Set([file_uri]), 1, my_config, new Map, file_uri, token, true);
23451
+ return token?.isCancellationRequested ? undefined : working_directory;
23452
+ }
23367
23453
  async discover_working_directory(directives, visited, depth, config, request_cache, current_uri, token, skip_backward_registration) {
23368
23454
  if (depth > config.max_backward_depth) {
23369
23455
  return;
@@ -23733,9 +23819,10 @@ class ScopeResolver {
23733
23819
  }
23734
23820
  }
23735
23821
  parse_content(uri, content, inherited_working_directory) {
23736
- const my_directive_result = this.directive_parser.parse(content, uri);
23737
- const my_lex_result = this.lexer.tokenize(content);
23738
- const my_parse_result = this.parser.parse(my_lex_result.tokens);
23822
+ const {
23823
+ directives: my_directive_result,
23824
+ analysis: my_analysis
23825
+ } = analyze_source(content, uri);
23739
23826
  const my_workspace_root = get_workspace_root_for_uri(this.workspace_roots, uri);
23740
23827
  let own_working_directory;
23741
23828
  if (my_directive_result.working_directory) {
@@ -23748,32 +23835,15 @@ class ScopeResolver {
23748
23835
  }
23749
23836
  }
23750
23837
  const effective_working_directory = own_working_directory ?? inherited_working_directory;
23751
- const my_analysis = this.analyzer.analyze(my_parse_result.ast, uri, undefined, {
23752
- working_directory: effective_working_directory
23753
- }, my_lex_result.tokens);
23754
- const my_caller_dir = path6.dirname(URI.parse(uri).fsPath);
23755
- const { timeline: cd_timeline } = build_cd_timeline({
23756
- starting_wd: effective_working_directory,
23757
- caller_dir: my_caller_dir,
23838
+ const all_forward_calls = prepare_forward_calls({
23839
+ uri,
23840
+ command_calls: my_analysis.forward_calls,
23841
+ directive_calls: my_directive_result.forward_calls ?? [],
23758
23842
  cd_commands: my_analysis.cd_commands,
23843
+ working_directory: effective_working_directory,
23759
23844
  workspace_roots: this.workspace_roots,
23760
23845
  fs: this.resolve_fs
23761
23846
  });
23762
- const restamped_command_calls = apply_cd_timeline(my_analysis.forward_calls, cd_timeline);
23763
- const directive_forward_calls = (my_directive_result.forward_calls ?? []).map((d) => ({
23764
- type: d.type,
23765
- raw_path: d.raw_path,
23766
- call_site_line: d.call_site_line,
23767
- range: d.range,
23768
- source: "directive",
23769
- is_static: true,
23770
- caller_uri: uri,
23771
- working_directory: effective_working_directory
23772
- }));
23773
- const all_forward_calls = [
23774
- ...restamped_command_calls,
23775
- ...directive_forward_calls
23776
- ];
23777
23847
  return {
23778
23848
  symbols: my_analysis.symbols,
23779
23849
  directives: my_directive_result.directives,
@@ -24607,9 +24677,8 @@ var init_scope_resolver = __esm(() => {
24607
24677
  init_esm();
24608
24678
  init_types();
24609
24679
  init_directive_parser();
24610
- init_lexer();
24611
- init_parser();
24612
24680
  init_analyzer();
24681
+ init_source_analysis();
24613
24682
  init_logger();
24614
24683
  init_lru_cache();
24615
24684
  init_dofile_locals();
@@ -25062,6 +25131,476 @@ var init_source_discovery_policy = __esm(() => {
25062
25131
  init_workspace_roots();
25063
25132
  });
25064
25133
 
25134
+ // node_modules/ignore/index.js
25135
+ var require_ignore = __commonJS((exports, module) => {
25136
+ function makeArray(subject) {
25137
+ return Array.isArray(subject) ? subject : [subject];
25138
+ }
25139
+ var UNDEFINED = undefined;
25140
+ var EMPTY = "";
25141
+ var SPACE = " ";
25142
+ var ESCAPE = "\\";
25143
+ var REGEX_TEST_BLANK_LINE = /^\s+$/;
25144
+ var REGEX_INVALID_TRAILING_BACKSLASH = /(?:[^\\]|^)\\$/;
25145
+ var REGEX_REPLACE_LEADING_EXCAPED_EXCLAMATION = /^\\!/;
25146
+ var REGEX_REPLACE_LEADING_EXCAPED_HASH = /^\\#/;
25147
+ var REGEX_SPLITALL_CRLF = /\r?\n/g;
25148
+ var REGEX_TEST_INVALID_PATH = /^\.{0,2}\/|^\.{1,2}$/;
25149
+ var REGEX_TEST_TRAILING_SLASH = /\/$/;
25150
+ var SLASH = "/";
25151
+ var TMP_KEY_IGNORE = "node-ignore";
25152
+ if (typeof Symbol !== "undefined") {
25153
+ TMP_KEY_IGNORE = Symbol.for("node-ignore");
25154
+ }
25155
+ var KEY_IGNORE = TMP_KEY_IGNORE;
25156
+ var define2 = (object, key, value) => {
25157
+ Object.defineProperty(object, key, { value });
25158
+ return value;
25159
+ };
25160
+ var REGEX_REGEXP_RANGE = /([0-z])-([0-z])/g;
25161
+ var RETURN_FALSE = () => false;
25162
+ var sanitizeRange = (range) => range.replace(REGEX_REGEXP_RANGE, (match, from, to) => from.charCodeAt(0) <= to.charCodeAt(0) ? match : EMPTY);
25163
+ var cleanRangeBackSlash = (slashes) => {
25164
+ const { length } = slashes;
25165
+ return slashes.slice(0, length - length % 2);
25166
+ };
25167
+ var REPLACERS = [
25168
+ [
25169
+ /^\uFEFF/,
25170
+ () => EMPTY
25171
+ ],
25172
+ [
25173
+ /((?:\\\\)*?)(\\?\s+)$/,
25174
+ (_, m1, m2) => m1 + (m2.indexOf("\\") === 0 ? SPACE : EMPTY)
25175
+ ],
25176
+ [
25177
+ /(\\+?)\s/g,
25178
+ (_, m1) => {
25179
+ const { length } = m1;
25180
+ return m1.slice(0, length - length % 2) + SPACE;
25181
+ }
25182
+ ],
25183
+ [
25184
+ /[\\$.|*+(){^]/g,
25185
+ (match) => `\\${match}`
25186
+ ],
25187
+ [
25188
+ /(?!\\)\?/g,
25189
+ () => "[^/]"
25190
+ ],
25191
+ [
25192
+ /^\//,
25193
+ () => "^"
25194
+ ],
25195
+ [
25196
+ /\//g,
25197
+ () => "\\/"
25198
+ ],
25199
+ [
25200
+ /^\^*\\\*\\\*\\\//,
25201
+ () => "^(?:.*\\/)?"
25202
+ ],
25203
+ [
25204
+ /^(?=[^^])/,
25205
+ function startingReplacer() {
25206
+ return !/\/(?!$)/.test(this) ? "(?:^|\\/)" : "^";
25207
+ }
25208
+ ],
25209
+ [
25210
+ /\\\/\\\*\\\*(?=\\\/|$)/g,
25211
+ (_, index, str) => index + 6 < str.length ? "(?:\\/[^\\/]+)*" : "\\/.+"
25212
+ ],
25213
+ [
25214
+ /(^|[^\\]+)(\\\*)+(?=.+)/g,
25215
+ (_, p1, p2) => {
25216
+ const unescaped = p2.replace(/\\\*/g, "[^\\/]*");
25217
+ return p1 + unescaped;
25218
+ }
25219
+ ],
25220
+ [
25221
+ /\\\\\\(?=[$.|*+(){^])/g,
25222
+ () => ESCAPE
25223
+ ],
25224
+ [
25225
+ /\\\\/g,
25226
+ () => ESCAPE
25227
+ ],
25228
+ [
25229
+ /(\\)?\[([^\]/]*?)(\\*)($|\])/g,
25230
+ (match, leadEscape, range, endEscape, close) => leadEscape === ESCAPE ? `\\[${range}${cleanRangeBackSlash(endEscape)}${close}` : close === "]" ? endEscape.length % 2 === 0 ? `[${sanitizeRange(range)}${endEscape}]` : "[]" : "[]"
25231
+ ],
25232
+ [
25233
+ /(?:[^*])$/,
25234
+ (match) => /\/$/.test(match) ? `${match}$` : `${match}(?=$|\\/$)`
25235
+ ]
25236
+ ];
25237
+ var REGEX_REPLACE_TRAILING_WILDCARD = /(^|\\\/)?\\\*$/;
25238
+ var MODE_IGNORE = "regex";
25239
+ var MODE_CHECK_IGNORE = "checkRegex";
25240
+ var UNDERSCORE = "_";
25241
+ var TRAILING_WILD_CARD_REPLACERS = {
25242
+ [MODE_IGNORE](_, p1) {
25243
+ const prefix = p1 ? `${p1}[^/]+` : "[^/]*";
25244
+ return `${prefix}(?=$|\\/$)`;
25245
+ },
25246
+ [MODE_CHECK_IGNORE](_, p1) {
25247
+ const prefix = p1 ? `${p1}[^/]*` : "[^/]*";
25248
+ return `${prefix}(?=$|\\/$)`;
25249
+ }
25250
+ };
25251
+ var makeRegexPrefix = (pattern) => REPLACERS.reduce((prev, [matcher, replacer]) => prev.replace(matcher, replacer.bind(pattern)), pattern);
25252
+ var isString = (subject) => typeof subject === "string";
25253
+ var checkPattern = (pattern) => pattern && isString(pattern) && !REGEX_TEST_BLANK_LINE.test(pattern) && !REGEX_INVALID_TRAILING_BACKSLASH.test(pattern) && pattern.indexOf("#") !== 0;
25254
+ var splitPattern = (pattern) => pattern.split(REGEX_SPLITALL_CRLF).filter(Boolean);
25255
+
25256
+ class IgnoreRule {
25257
+ constructor(pattern, mark, body, ignoreCase, negative, prefix) {
25258
+ this.pattern = pattern;
25259
+ this.mark = mark;
25260
+ this.negative = negative;
25261
+ define2(this, "body", body);
25262
+ define2(this, "ignoreCase", ignoreCase);
25263
+ define2(this, "regexPrefix", prefix);
25264
+ }
25265
+ get regex() {
25266
+ const key = UNDERSCORE + MODE_IGNORE;
25267
+ if (this[key]) {
25268
+ return this[key];
25269
+ }
25270
+ return this._make(MODE_IGNORE, key);
25271
+ }
25272
+ get checkRegex() {
25273
+ const key = UNDERSCORE + MODE_CHECK_IGNORE;
25274
+ if (this[key]) {
25275
+ return this[key];
25276
+ }
25277
+ return this._make(MODE_CHECK_IGNORE, key);
25278
+ }
25279
+ _make(mode, key) {
25280
+ const str = this.regexPrefix.replace(REGEX_REPLACE_TRAILING_WILDCARD, TRAILING_WILD_CARD_REPLACERS[mode]);
25281
+ const regex = this.ignoreCase ? new RegExp(str, "i") : new RegExp(str);
25282
+ return define2(this, key, regex);
25283
+ }
25284
+ }
25285
+ var createRule = ({
25286
+ pattern,
25287
+ mark
25288
+ }, ignoreCase) => {
25289
+ let negative = false;
25290
+ let body = pattern;
25291
+ if (body.indexOf("!") === 0) {
25292
+ negative = true;
25293
+ body = body.substr(1);
25294
+ }
25295
+ body = body.replace(REGEX_REPLACE_LEADING_EXCAPED_EXCLAMATION, "!").replace(REGEX_REPLACE_LEADING_EXCAPED_HASH, "#");
25296
+ const regexPrefix = makeRegexPrefix(body);
25297
+ return new IgnoreRule(pattern, mark, body, ignoreCase, negative, regexPrefix);
25298
+ };
25299
+
25300
+ class RuleManager {
25301
+ constructor(ignoreCase) {
25302
+ this._ignoreCase = ignoreCase;
25303
+ this._rules = [];
25304
+ }
25305
+ _add(pattern) {
25306
+ if (pattern && pattern[KEY_IGNORE]) {
25307
+ this._rules = this._rules.concat(pattern._rules._rules);
25308
+ this._added = true;
25309
+ return;
25310
+ }
25311
+ if (isString(pattern)) {
25312
+ pattern = {
25313
+ pattern
25314
+ };
25315
+ }
25316
+ if (checkPattern(pattern.pattern)) {
25317
+ const rule = createRule(pattern, this._ignoreCase);
25318
+ this._added = true;
25319
+ this._rules.push(rule);
25320
+ }
25321
+ }
25322
+ add(pattern) {
25323
+ this._added = false;
25324
+ makeArray(isString(pattern) ? splitPattern(pattern) : pattern).forEach(this._add, this);
25325
+ return this._added;
25326
+ }
25327
+ test(path10, checkUnignored, mode) {
25328
+ let ignored = false;
25329
+ let unignored = false;
25330
+ let matchedRule;
25331
+ this._rules.forEach((rule) => {
25332
+ const { negative } = rule;
25333
+ if (unignored === negative && ignored !== unignored || negative && !ignored && !unignored && !checkUnignored) {
25334
+ return;
25335
+ }
25336
+ const matched = rule[mode].test(path10);
25337
+ if (!matched) {
25338
+ return;
25339
+ }
25340
+ ignored = !negative;
25341
+ unignored = negative;
25342
+ matchedRule = negative ? UNDEFINED : rule;
25343
+ });
25344
+ const ret = {
25345
+ ignored,
25346
+ unignored
25347
+ };
25348
+ if (matchedRule) {
25349
+ ret.rule = matchedRule;
25350
+ }
25351
+ return ret;
25352
+ }
25353
+ }
25354
+ var throwError = (message, Ctor) => {
25355
+ throw new Ctor(message);
25356
+ };
25357
+ var checkPath = (path10, originalPath, doThrow) => {
25358
+ if (!isString(path10)) {
25359
+ return doThrow(`path must be a string, but got \`${originalPath}\``, TypeError);
25360
+ }
25361
+ if (!path10) {
25362
+ return doThrow(`path must not be empty`, TypeError);
25363
+ }
25364
+ if (checkPath.isNotRelative(path10)) {
25365
+ const r = "`path.relative()`d";
25366
+ return doThrow(`path should be a ${r} string, but got "${originalPath}"`, RangeError);
25367
+ }
25368
+ return true;
25369
+ };
25370
+ var isNotRelative = (path10) => REGEX_TEST_INVALID_PATH.test(path10);
25371
+ checkPath.isNotRelative = isNotRelative;
25372
+ checkPath.convert = (p) => p;
25373
+
25374
+ class Ignore {
25375
+ constructor({
25376
+ ignorecase = true,
25377
+ ignoreCase = ignorecase,
25378
+ allowRelativePaths = false
25379
+ } = {}) {
25380
+ define2(this, KEY_IGNORE, true);
25381
+ this._rules = new RuleManager(ignoreCase);
25382
+ this._strictPathCheck = !allowRelativePaths;
25383
+ this._initCache();
25384
+ }
25385
+ _initCache() {
25386
+ this._ignoreCache = Object.create(null);
25387
+ this._testCache = Object.create(null);
25388
+ }
25389
+ add(pattern) {
25390
+ if (this._rules.add(pattern)) {
25391
+ this._initCache();
25392
+ }
25393
+ return this;
25394
+ }
25395
+ addPattern(pattern) {
25396
+ return this.add(pattern);
25397
+ }
25398
+ _test(originalPath, cache, checkUnignored, slices) {
25399
+ const path10 = originalPath && checkPath.convert(originalPath);
25400
+ checkPath(path10, originalPath, this._strictPathCheck ? throwError : RETURN_FALSE);
25401
+ return this._t(path10, cache, checkUnignored, slices);
25402
+ }
25403
+ checkIgnore(path10) {
25404
+ if (!REGEX_TEST_TRAILING_SLASH.test(path10)) {
25405
+ return this.test(path10);
25406
+ }
25407
+ const slices = path10.split(SLASH).filter(Boolean);
25408
+ slices.pop();
25409
+ if (slices.length) {
25410
+ const parent = this._t(slices.join(SLASH) + SLASH, this._testCache, true, slices);
25411
+ if (parent.ignored) {
25412
+ return parent;
25413
+ }
25414
+ }
25415
+ return this._rules.test(path10, false, MODE_CHECK_IGNORE);
25416
+ }
25417
+ _t(path10, cache, checkUnignored, slices) {
25418
+ if (path10 in cache) {
25419
+ return cache[path10];
25420
+ }
25421
+ if (!slices) {
25422
+ slices = path10.split(SLASH).filter(Boolean);
25423
+ }
25424
+ slices.pop();
25425
+ if (!slices.length) {
25426
+ return cache[path10] = this._rules.test(path10, checkUnignored, MODE_IGNORE);
25427
+ }
25428
+ const parent = this._t(slices.join(SLASH) + SLASH, cache, checkUnignored, slices);
25429
+ return cache[path10] = parent.ignored ? parent : this._rules.test(path10, checkUnignored, MODE_IGNORE);
25430
+ }
25431
+ ignores(path10) {
25432
+ return this._test(path10, this._ignoreCache, false).ignored;
25433
+ }
25434
+ createFilter() {
25435
+ return (path10) => !this.ignores(path10);
25436
+ }
25437
+ filter(paths) {
25438
+ return makeArray(paths).filter(this.createFilter());
25439
+ }
25440
+ test(path10) {
25441
+ return this._test(path10, this._testCache, true);
25442
+ }
25443
+ }
25444
+ var factory = (options) => new Ignore(options);
25445
+ var isPathValid = (path10) => checkPath(path10 && checkPath.convert(path10), path10, RETURN_FALSE);
25446
+ var setupWindows = () => {
25447
+ const makePosix = (str) => /^\\\\\?\\/.test(str) || /["<>|\u0000-\u001F]+/u.test(str) ? str : str.replace(/\\/g, "/");
25448
+ checkPath.convert = makePosix;
25449
+ const REGEX_TEST_WINDOWS_PATH_ABSOLUTE = /^[a-z]:\//i;
25450
+ checkPath.isNotRelative = (path10) => REGEX_TEST_WINDOWS_PATH_ABSOLUTE.test(path10) || isNotRelative(path10);
25451
+ };
25452
+ if (typeof process !== "undefined" && process.platform === "win32") {
25453
+ setupWindows();
25454
+ }
25455
+ module.exports = factory;
25456
+ factory.default = factory;
25457
+ module.exports.isPathValid = isPathValid;
25458
+ define2(module.exports, Symbol.for("setupWindows"), setupWindows);
25459
+ });
25460
+
25461
+ // src/utils/gitignore-matcher.ts
25462
+ import * as fs9 from "fs";
25463
+ import * as path10 from "path";
25464
+ function rebase_patterns(content, relative_directory) {
25465
+ const pattern_content = content.startsWith("\uFEFF") ? content.slice(1) : content;
25466
+ const the_lines = pattern_content.split(IGNORE_LINE_BREAK);
25467
+ if (relative_directory === "")
25468
+ return the_lines;
25469
+ LITERAL_DIRECTORY_METACHARACTERS.lastIndex = 0;
25470
+ const prefix = relative_directory.replace(LITERAL_DIRECTORY_METACHARACTERS, "\\$&");
25471
+ const the_patterns = [];
25472
+ for (const my_line of the_lines) {
25473
+ if (BLANK_PATTERN.test(my_line) || my_line.startsWith("#"))
25474
+ continue;
25475
+ const negative = my_line.startsWith("!");
25476
+ const body = negative ? my_line.slice(1) : my_line;
25477
+ const shape = body.replace(TRAILING_PATTERN_WHITESPACE, "");
25478
+ if (shape === "" || shape === "/")
25479
+ continue;
25480
+ const anchored = body.startsWith("/") || MIDDLE_SLASH.test(shape);
25481
+ const relative_pattern = (body.startsWith("/") ? body.slice(1) : body).replace(ESCAPED_PATTERN_PREFIX, "$1");
25482
+ the_patterns.push(`${negative ? "!" : ""}/${prefix}/` + `${anchored ? "" : "**/"}${relative_pattern}`);
25483
+ }
25484
+ return the_patterns;
25485
+ }
25486
+ function is_missing(error) {
25487
+ return typeof error === "object" && error !== null && "code" in error && (error.code === "ENOENT" || error.code === "ENOTDIR");
25488
+ }
25489
+ function contains_path(root, target) {
25490
+ const relative6 = path10.relative(root, target);
25491
+ return relative6 !== ".." && !relative6.startsWith(`..${path10.sep}`) && !path10.isAbsolute(relative6);
25492
+ }
25493
+ function create_gitignore_matcher(workspace_roots, respect_gitignore = true) {
25494
+ if (!respect_gitignore || workspace_roots.length === 0) {
25495
+ return DISABLED_MATCHER;
25496
+ }
25497
+ let warned = false;
25498
+ function warn_unreadable(file_path, error) {
25499
+ if (warned || is_missing(error))
25500
+ return;
25501
+ warned = true;
25502
+ const detail = error instanceof Error ? error.message : String(error);
25503
+ logger.warn(`Cannot read Gitignore rules at ${file_path}: ${detail}. ` + "Continuing with the available rules.");
25504
+ }
25505
+ function find_rule_root(workspace_root) {
25506
+ let directory = workspace_root;
25507
+ while (true) {
25508
+ const marker_path = path10.join(directory, ".git");
25509
+ try {
25510
+ const marker = fs9.lstatSync(marker_path);
25511
+ if (marker.isDirectory() || marker.isFile())
25512
+ return directory;
25513
+ } catch (error) {
25514
+ warn_unreadable(marker_path, error);
25515
+ }
25516
+ const parent = path10.dirname(directory);
25517
+ if (parent === directory)
25518
+ return workspace_root;
25519
+ directory = parent;
25520
+ }
25521
+ }
25522
+ function read_rules(scope, directory, inherited_rules) {
25523
+ const ignore_path = path10.join(directory, ".gitignore");
25524
+ try {
25525
+ if (fs9.lstatSync(ignore_path).isFile()) {
25526
+ const content = fs9.readFileSync(ignore_path, "utf8");
25527
+ const relative_directory = path10.relative(scope.rule_root, directory).split(path10.sep).join("/");
25528
+ return import_ignore.default({ ignorecase: false }).add(inherited_rules ?? []).add(rebase_patterns(content, relative_directory));
25529
+ }
25530
+ } catch (error) {
25531
+ warn_unreadable(ignore_path, error);
25532
+ }
25533
+ return inherited_rules ?? import_ignore.default({ ignorecase: false });
25534
+ }
25535
+ function matches_rules(context, absolute_path, kind) {
25536
+ if (context.ignored)
25537
+ return true;
25538
+ const relative6 = path10.relative(context.rule_root, absolute_path).split(path10.sep).join("/");
25539
+ return context.rules.ignores(kind === "directory" ? `${relative6}/` : relative6);
25540
+ }
25541
+ function directory_context(scope, directory) {
25542
+ const cached = scope.directories.get(directory);
25543
+ if (cached)
25544
+ return cached;
25545
+ const parent = path10.relative(scope.rule_root, directory) === "" ? undefined : directory_context(scope, path10.dirname(directory));
25546
+ const ignored = parent !== undefined && matches_rules(parent, directory, "directory");
25547
+ const context = {
25548
+ rule_root: scope.rule_root,
25549
+ ignored,
25550
+ rules: ignored && parent ? parent.rules : read_rules(scope, directory, parent?.rules)
25551
+ };
25552
+ scope.directories.set(directory, context);
25553
+ return context;
25554
+ }
25555
+ const the_scopes = Array.from(new Set(workspace_roots.map((my_root) => path10.resolve(my_root)))).sort((a, b) => b.length - a.length).map((workspace_root) => ({
25556
+ workspace_root,
25557
+ rule_root: find_rule_root(workspace_root),
25558
+ directories: new Map
25559
+ }));
25560
+ const the_watch_directories = new Map;
25561
+ for (const my_scope of the_scopes) {
25562
+ the_watch_directories.set(my_scope.workspace_root, true);
25563
+ let directory = my_scope.workspace_root;
25564
+ while (directory !== my_scope.rule_root) {
25565
+ directory = path10.dirname(directory);
25566
+ if (!the_watch_directories.has(directory)) {
25567
+ the_watch_directories.set(directory, false);
25568
+ }
25569
+ }
25570
+ }
25571
+ return {
25572
+ watch_directories: Array.from(the_watch_directories, ([directory, recursive]) => ({ directory, recursive })),
25573
+ is_ignored(absolute_path, kind) {
25574
+ const target = path10.resolve(absolute_path);
25575
+ for (const my_scope of the_scopes) {
25576
+ if (!contains_path(my_scope.workspace_root, target))
25577
+ continue;
25578
+ if (path10.relative(my_scope.workspace_root, target) === "") {
25579
+ return false;
25580
+ }
25581
+ const context = directory_context(my_scope, path10.dirname(target));
25582
+ return matches_rules(context, target, kind);
25583
+ }
25584
+ return false;
25585
+ }
25586
+ };
25587
+ }
25588
+ var import_ignore, DISABLED_MATCHER, IGNORE_LINE_BREAK, BLANK_PATTERN, TRAILING_PATTERN_WHITESPACE, MIDDLE_SLASH, LITERAL_DIRECTORY_METACHARACTERS, ESCAPED_PATTERN_PREFIX;
25589
+ var init_gitignore_matcher = __esm(() => {
25590
+ init_logger();
25591
+ import_ignore = __toESM(require_ignore(), 1);
25592
+ DISABLED_MATCHER = {
25593
+ is_ignored: () => false,
25594
+ watch_directories: []
25595
+ };
25596
+ IGNORE_LINE_BREAK = /\r?\n/;
25597
+ BLANK_PATTERN = /^\s*$/;
25598
+ TRAILING_PATTERN_WHITESPACE = /\s+$/;
25599
+ MIDDLE_SLASH = /\/(?!$)/;
25600
+ LITERAL_DIRECTORY_METACHARACTERS = /[\\*[\]]/g;
25601
+ ESCAPED_PATTERN_PREFIX = /^\\([!#])/;
25602
+ });
25603
+
25065
25604
  // node_modules/picomatch/lib/constants.js
25066
25605
  var require_constants = __commonJS((exports, module) => {
25067
25606
  var WIN_SLASH = "\\\\/";
@@ -25260,8 +25799,8 @@ var require_utils = __commonJS((exports) => {
25260
25799
  }
25261
25800
  return output;
25262
25801
  };
25263
- exports.basename = (path10, { windows } = {}) => {
25264
- const segs = path10.split(windows ? /[\\/]/ : "/");
25802
+ exports.basename = (path11, { windows } = {}) => {
25803
+ const segs = path11.split(windows ? /[\\/]/ : "/");
25265
25804
  const last = segs[segs.length - 1];
25266
25805
  if (last === "") {
25267
25806
  return segs[segs.length - 2];
@@ -26742,7 +27281,7 @@ var require_picomatch2 = __commonJS((exports, module) => {
26742
27281
  });
26743
27282
 
26744
27283
  // src/utils/exclude-matcher.ts
26745
- import path10 from "path";
27284
+ import path11 from "path";
26746
27285
  function normalize_pattern(raw) {
26747
27286
  const trimmed = raw.trim();
26748
27287
  if (trimmed === "")
@@ -26764,13 +27303,13 @@ function derive_dir_pattern(pattern) {
26764
27303
  return stripped === "" ? pattern : stripped;
26765
27304
  }
26766
27305
  function relative_to_containing_root(abs_path, workspace_roots) {
26767
- const target = path10.resolve(abs_path);
27306
+ const target = path11.resolve(abs_path);
26768
27307
  let best = null;
26769
27308
  let best_root_length = -1;
26770
27309
  for (const my_root of workspace_roots) {
26771
- const root = path10.resolve(my_root);
26772
- const my_relative = path10.relative(root, target);
26773
- const contained = my_relative === "" || my_relative !== ".." && !my_relative.startsWith(`..${path10.sep}`) && !path10.isAbsolute(my_relative);
27310
+ const root = path11.resolve(my_root);
27311
+ const my_relative = path11.relative(root, target);
27312
+ const contained = my_relative === "" || my_relative !== ".." && !my_relative.startsWith(`..${path11.sep}`) && !path11.isAbsolute(my_relative);
26774
27313
  if (contained && root.length > best_root_length) {
26775
27314
  best = my_relative;
26776
27315
  best_root_length = root.length;
@@ -26778,7 +27317,7 @@ function relative_to_containing_root(abs_path, workspace_roots) {
26778
27317
  }
26779
27318
  if (best === null)
26780
27319
  return null;
26781
- return best.split(path10.sep).join("/");
27320
+ return best.split(path11.sep).join("/");
26782
27321
  }
26783
27322
  function create_exclude_matcher(patterns) {
26784
27323
  const compiled = [];
@@ -26818,12 +27357,12 @@ function create_exclude_matcher(patterns) {
26818
27357
  return {
26819
27358
  is_empty: false,
26820
27359
  is_excluded_file(abs_path, workspace_roots) {
26821
- const relative5 = relative_to_containing_root(abs_path, workspace_roots);
26822
- if (relative5 === null || relative5 === "")
27360
+ const relative6 = relative_to_containing_root(abs_path, workspace_roots);
27361
+ if (relative6 === null || relative6 === "")
26823
27362
  return false;
26824
27363
  let excluded = false;
26825
27364
  for (const my_rule of compiled) {
26826
- if (my_rule.match(relative5)) {
27365
+ if (my_rule.match(relative6)) {
26827
27366
  excluded = !my_rule.is_negated;
26828
27367
  }
26829
27368
  }
@@ -26832,8 +27371,8 @@ function create_exclude_matcher(patterns) {
26832
27371
  is_excluded_dir(abs_path, workspace_roots) {
26833
27372
  if (dir_match === null)
26834
27373
  return false;
26835
- const relative5 = relative_to_containing_root(abs_path, workspace_roots);
26836
- return relative5 !== null && relative5 !== "" && dir_match(relative5);
27374
+ const relative6 = relative_to_containing_root(abs_path, workspace_roots);
27375
+ return relative6 !== null && relative6 !== "" && dir_match(relative6);
26837
27376
  }
26838
27377
  };
26839
27378
  }
@@ -26849,15 +27388,13 @@ var init_exclude_matcher = __esm(() => {
26849
27388
  });
26850
27389
 
26851
27390
  // src/indexer/index.ts
26852
- import * as fs9 from "fs";
26853
- import * as path11 from "path";
27391
+ import * as fs10 from "fs";
27392
+ import * as path12 from "path";
26854
27393
  var MAX_PARALLEL = 4, YIELD_INTERVAL_MS = 100, INDEX_DEBOUNCE_MS = 200, WorkspaceIndexer;
26855
27394
  var init_indexer = __esm(() => {
26856
27395
  init_esm();
26857
- init_lexer();
26858
- init_parser();
26859
27396
  init_analyzer();
26860
- init_directive_parser();
27397
+ init_source_analysis();
26861
27398
  init_scope_resolver();
26862
27399
  init_context_tracker();
26863
27400
  init_logger();
@@ -26867,6 +27404,7 @@ var init_indexer = __esm(() => {
26867
27404
  init_findalias_resolver();
26868
27405
  init_file_path_utils();
26869
27406
  init_source_discovery_policy();
27407
+ init_gitignore_matcher();
26870
27408
  init_exclude_matcher();
26871
27409
  WorkspaceIndexer = class WorkspaceIndexer {
26872
27410
  symbol_index = new Map;
@@ -26874,10 +27412,6 @@ var init_indexer = __esm(() => {
26874
27412
  token_index = new Map;
26875
27413
  context_ranges_index = new Map;
26876
27414
  enabled = true;
26877
- lexer = new StataLexer;
26878
- parser = new StataParser;
26879
- analyzer = new SemanticAnalyzer;
26880
- directive_parser = new DirectiveParser;
26881
27415
  ado_paths = [];
26882
27416
  help_search_paths = [];
26883
27417
  findalias_resolver = new FindaliasResolver;
@@ -26892,6 +27426,8 @@ var init_indexer = __esm(() => {
26892
27426
  cancelled = false;
26893
27427
  size_threshold_bytes = 512 * 1024;
26894
27428
  exclude_matcher = create_exclude_matcher([]);
27429
+ respect_gitignore = true;
27430
+ gitignore_matcher = create_gitignore_matcher([]);
26895
27431
  skipped_files = new Map;
26896
27432
  max_indexed_files = 1000;
26897
27433
  max_files_reached = false;
@@ -27001,16 +27537,17 @@ var init_indexer = __esm(() => {
27001
27537
  async initialize(workspace_folders, ado_paths = []) {
27002
27538
  const generation = ++this.scan_generation;
27003
27539
  this.cancelled = false;
27004
- if (!this.enabled) {
27005
- this.dependency_graph?.mark_scan_complete();
27006
- return;
27007
- }
27008
27540
  this.ado_paths = ado_paths;
27009
- this.workspace_roots = workspace_folders.map((f) => path11.resolve(f));
27541
+ this.workspace_roots = workspace_folders.map((f) => path12.resolve(f));
27010
27542
  this.scan_roots = [
27011
27543
  ...this.workspace_roots,
27012
- ...ado_paths.map((my_path) => path11.resolve(my_path))
27544
+ ...ado_paths.map((my_path) => path12.resolve(my_path))
27013
27545
  ];
27546
+ this.gitignore_matcher = create_gitignore_matcher(this.workspace_roots, this.respect_gitignore);
27547
+ if (!this.enabled) {
27548
+ this.dependency_graph?.mark_scan_complete();
27549
+ return;
27550
+ }
27014
27551
  this.help_search_paths = discover_stata_ado_paths();
27015
27552
  const start_time = Date.now();
27016
27553
  for (const folder of [...workspace_folders, ...this.ado_paths]) {
@@ -27032,8 +27569,10 @@ var init_indexer = __esm(() => {
27032
27569
  async scan_directory(dir_path, generation) {
27033
27570
  if (!this.is_active_generation(generation))
27034
27571
  return;
27572
+ if (this.gitignore_matcher.is_ignored(dir_path, "directory"))
27573
+ return;
27035
27574
  try {
27036
- const entries = await fs9.promises.readdir(dir_path, {
27575
+ const entries = await fs10.promises.readdir(dir_path, {
27037
27576
  withFileTypes: true
27038
27577
  });
27039
27578
  if (!this.is_active_generation(generation))
@@ -27042,7 +27581,7 @@ var init_indexer = __esm(() => {
27042
27581
  for (const entry of entries) {
27043
27582
  if (!this.is_active_generation(generation))
27044
27583
  break;
27045
- const entry_path = path11.join(dir_path, entry.name);
27584
+ const entry_path = path12.join(dir_path, entry.name);
27046
27585
  if (entry.isDirectory()) {
27047
27586
  if (entry.name.startsWith(".")) {
27048
27587
  continue;
@@ -27052,6 +27591,8 @@ var init_indexer = __esm(() => {
27052
27591
  }
27053
27592
  await this.scan_directory(entry_path, generation);
27054
27593
  } else if (entry.isFile() && hasStataExtension(entry.name)) {
27594
+ if (this.is_gitignored(entry_path))
27595
+ continue;
27055
27596
  if (!this.exclude_matcher.is_empty && this.exclude_matcher.is_excluded_file(entry_path, this.workspace_roots)) {
27056
27597
  continue;
27057
27598
  }
@@ -27074,7 +27615,7 @@ var init_indexer = __esm(() => {
27074
27615
  const now = Date.now();
27075
27616
  if (now - last_yield_time.value > YIELD_INTERVAL_MS) {
27076
27617
  last_yield_time.value = now;
27077
- await new Promise((resolve10) => setImmediate(resolve10));
27618
+ await new Promise((resolve11) => setImmediate(resolve11));
27078
27619
  }
27079
27620
  }
27080
27621
  };
@@ -27120,6 +27661,8 @@ var init_indexer = __esm(() => {
27120
27661
  const file_uri = URI.file(file_path).toString();
27121
27662
  if (is_hidden_source_path(file_path, this.scan_roots))
27122
27663
  return;
27664
+ if (this.is_gitignored(file_path))
27665
+ return;
27123
27666
  if (!this.exclude_matcher.is_empty && this.exclude_matcher.is_excluded_file(file_path, this.workspace_roots)) {
27124
27667
  this.clear_stale_entry(file_uri);
27125
27668
  return;
@@ -27128,7 +27671,7 @@ var init_indexer = __esm(() => {
27128
27671
  if (!already_indexed && this.should_skip_for_max_indexed_files(file_uri))
27129
27672
  return;
27130
27673
  try {
27131
- const stats = await fs9.promises.stat(file_path);
27674
+ const stats = await fs10.promises.stat(file_path);
27132
27675
  if (!this.is_active_generation(generation))
27133
27676
  return;
27134
27677
  if (stats.size > this.size_threshold_bytes) {
@@ -27138,56 +27681,41 @@ var init_indexer = __esm(() => {
27138
27681
  this.metrics.files_skipped++;
27139
27682
  return;
27140
27683
  }
27141
- const content = await fs9.promises.readFile(file_path, "utf8");
27684
+ const content = await fs10.promises.readFile(file_path, "utf8");
27142
27685
  if (!this.is_active_generation(generation))
27143
27686
  return;
27144
27687
  if (!already_indexed && this.should_skip_for_max_indexed_files(file_uri))
27145
27688
  return;
27146
- if (path11.extname(file_path).toLowerCase() === ".mata") {
27689
+ if (path12.extname(file_path).toLowerCase() === ".mata") {
27147
27690
  await this.index_mata_file(content, file_uri, generation);
27148
27691
  return;
27149
27692
  }
27150
- const directive_result = this.directive_parser.parse(content, file_uri);
27151
- const lexResult = this.lexer.tokenize(content);
27152
- const parseResult = this.parser.parse(lexResult.tokens);
27693
+ const source_analysis = analyze_source(content, file_uri);
27694
+ const directive_result = source_analysis.directives;
27695
+ const analyzeResult = source_analysis.analysis;
27153
27696
  const workspace_root = get_workspace_root_for_path(this.workspace_roots, file_path);
27154
- const analyzeResult = this.analyzer.analyze(parseResult.ast, file_uri, undefined, undefined, lexResult.tokens);
27155
27697
  const own_working_directory = directive_result.working_directory ? resolve_working_directory_directive(directive_result.working_directory, workspace_root) : undefined;
27156
27698
  let effective_working_directory = own_working_directory;
27157
27699
  if (own_working_directory === undefined && this.scope_resolver) {
27158
27700
  effective_working_directory = await this.scope_resolver.resolve_inherited_working_directory(directive_result.directives, file_uri, directive_result.standalone !== undefined, this.scope_resolver_config);
27159
27701
  }
27160
- const my_caller_dir = path11.dirname(file_path);
27161
- const { timeline: cd_timeline } = build_cd_timeline({
27162
- starting_wd: effective_working_directory,
27163
- caller_dir: my_caller_dir,
27702
+ const all_forward_calls = prepare_forward_calls({
27703
+ uri: file_uri,
27704
+ command_calls: analyzeResult.forward_calls,
27705
+ directive_calls: directive_result.forward_calls ?? [],
27164
27706
  cd_commands: analyzeResult.cd_commands,
27707
+ working_directory: effective_working_directory,
27165
27708
  workspace_roots: this.workspace_roots
27166
27709
  });
27167
- const stamped_analyzer_calls = apply_cd_timeline(analyzeResult.forward_calls, cd_timeline);
27168
27710
  const context_tracker = new ContextTracker;
27169
- context_tracker.initialize_from_tokens(lexResult.tokens, content);
27711
+ context_tracker.initialize_from_tokens(source_analysis.tokens, content);
27170
27712
  const context_ranges = context_tracker.get_all_context_ranges();
27171
27713
  if (!this.is_active_generation(generation))
27172
27714
  return;
27173
27715
  if (!already_indexed && this.should_skip_for_max_indexed_files(file_uri))
27174
27716
  return;
27175
- let all_forward_calls = stamped_analyzer_calls;
27176
- if (directive_result.forward_calls && directive_result.forward_calls.length > 0) {
27177
- const directive_forward_calls = directive_result.forward_calls.map((d) => ({
27178
- type: d.type,
27179
- raw_path: d.raw_path,
27180
- call_site_line: d.call_site_line,
27181
- range: d.range,
27182
- source: "directive",
27183
- is_static: true,
27184
- caller_uri: file_uri,
27185
- working_directory: effective_working_directory
27186
- }));
27187
- all_forward_calls = [
27188
- ...stamped_analyzer_calls,
27189
- ...directive_forward_calls
27190
- ].sort((a, b) => a.call_site_line - b.call_site_line);
27717
+ if ((directive_result.forward_calls?.length ?? 0) > 0) {
27718
+ all_forward_calls.sort((a, b) => a.call_site_line - b.call_site_line);
27191
27719
  }
27192
27720
  if (this.dependency_graph) {
27193
27721
  const graph_result = this.dependency_graph.update_caller(file_uri, all_forward_calls);
@@ -27195,7 +27723,7 @@ var init_indexer = __esm(() => {
27195
27723
  this.on_graph_change_callback(graph_result.changed_callees);
27196
27724
  }
27197
27725
  }
27198
- this.token_index.set(file_uri, lexResult.tokens);
27726
+ this.token_index.set(file_uri, source_analysis.tokens);
27199
27727
  this.context_ranges_index.set(file_uri, context_ranges);
27200
27728
  const is_new_entry = !this.symbol_index.has(file_uri);
27201
27729
  this.symbol_index.set(file_uri, {
@@ -27274,6 +27802,8 @@ var init_indexer = __esm(() => {
27274
27802
  return;
27275
27803
  if (is_hidden_source_path(file_path, this.scan_roots))
27276
27804
  return;
27805
+ if (this.is_gitignored(file_path))
27806
+ return;
27277
27807
  const existing = this.pending_updates.get(file_path);
27278
27808
  if (existing) {
27279
27809
  clearTimeout(existing);
@@ -27298,7 +27828,7 @@ var init_indexer = __esm(() => {
27298
27828
  break;
27299
27829
  this.update_queue.delete(file_path);
27300
27830
  await this.index_file(file_path, generation);
27301
- await new Promise((resolve10) => setImmediate(resolve10));
27831
+ await new Promise((resolve11) => setImmediate(resolve11));
27302
27832
  }
27303
27833
  } finally {
27304
27834
  this.is_processing_queue = false;
@@ -27330,10 +27860,12 @@ var init_indexer = __esm(() => {
27330
27860
  this.version = 0;
27331
27861
  this.cancelled = false;
27332
27862
  this.workspace_roots = [];
27863
+ this.gitignore_matcher = create_gitignore_matcher([]);
27333
27864
  }
27334
27865
  configure(config) {
27335
27866
  this.scope_resolver_config = scope_resolver_config_for(config);
27336
27867
  this.exclude_matcher = create_exclude_matcher(config.exclude ?? []);
27868
+ this.respect_gitignore = config.workspace?.respectGitignore !== false;
27337
27869
  const threshold = config?.indexing?.maxFileSizeBytes;
27338
27870
  if (typeof threshold === "number" && threshold > 0) {
27339
27871
  this.size_threshold_bytes = threshold;
@@ -27348,6 +27880,9 @@ var init_indexer = __esm(() => {
27348
27880
  this.enabled = true;
27349
27881
  }
27350
27882
  }
27883
+ is_gitignored(file_path) {
27884
+ return this.gitignore_matcher.is_ignored(file_path, "file");
27885
+ }
27351
27886
  get_skipped_files() {
27352
27887
  return new Map(this.skipped_files);
27353
27888
  }
@@ -27557,17 +28092,17 @@ var init_indexer = __esm(() => {
27557
28092
  ...this.help_search_paths
27558
28093
  ];
27559
28094
  for (const my_dir of the_search_dirs) {
27560
- const my_subdir_path = path11.join(my_dir, my_first_letter, my_basename);
28095
+ const my_subdir_path = path12.join(my_dir, my_first_letter, my_basename);
27561
28096
  try {
27562
- await fs9.promises.access(my_subdir_path);
28097
+ await fs10.promises.access(my_subdir_path);
27563
28098
  return my_subdir_path;
27564
28099
  } catch {}
27565
- const my_direct_path = path11.join(my_dir, my_basename);
28100
+ const my_direct_path = path12.join(my_dir, my_basename);
27566
28101
  try {
27567
- await fs9.promises.access(my_direct_path);
28102
+ await fs10.promises.access(my_direct_path);
27568
28103
  return my_direct_path;
27569
28104
  } catch {}
27570
- if (!this.workspace_roots.includes(path11.resolve(my_dir))) {
28105
+ if (!this.workspace_roots.includes(path12.resolve(my_dir))) {
27571
28106
  continue;
27572
28107
  }
27573
28108
  const my_recursive_match = await this.find_sthlp_file_recursive(my_dir, my_basename);
@@ -27591,14 +28126,14 @@ var init_indexer = __esm(() => {
27591
28126
  ...this.help_search_paths
27592
28127
  ];
27593
28128
  for (const my_dir of the_search_dirs) {
27594
- const my_subdir_path = path11.join(my_dir, my_first_letter, my_basename);
28129
+ const my_subdir_path = path12.join(my_dir, my_first_letter, my_basename);
27595
28130
  try {
27596
- await fs9.promises.access(my_subdir_path);
28131
+ await fs10.promises.access(my_subdir_path);
27597
28132
  return my_subdir_path;
27598
28133
  } catch {}
27599
- const my_direct_path = path11.join(my_dir, my_basename);
28134
+ const my_direct_path = path12.join(my_dir, my_basename);
27600
28135
  try {
27601
- await fs9.promises.access(my_direct_path);
28136
+ await fs10.promises.access(my_direct_path);
27602
28137
  return my_direct_path;
27603
28138
  } catch {}
27604
28139
  }
@@ -27606,9 +28141,9 @@ var init_indexer = __esm(() => {
27606
28141
  }
27607
28142
  async list_matching_sthlp(dir, prefix) {
27608
28143
  try {
27609
- const the_entries = await fs9.promises.readdir(dir);
28144
+ const the_entries = await fs10.promises.readdir(dir);
27610
28145
  const the_matches = the_entries.filter((my_entry) => my_entry.startsWith(prefix) && my_entry.endsWith(".sthlp")).sort();
27611
- return the_matches.map((my_entry) => path11.join(dir, my_entry));
28146
+ return the_matches.map((my_entry) => path12.join(dir, my_entry));
27612
28147
  } catch {
27613
28148
  return [];
27614
28149
  }
@@ -27632,7 +28167,7 @@ var init_indexer = __esm(() => {
27632
28167
  const my_prefix = `${my_variant}_`;
27633
28168
  const my_first_letter = my_variant.charAt(0).toLowerCase();
27634
28169
  for (const my_dir of the_search_dirs) {
27635
- const my_subdir = path11.join(my_dir, my_first_letter);
28170
+ const my_subdir = path12.join(my_dir, my_first_letter);
27636
28171
  const the_subdir_matches = await this.list_matching_sthlp(my_subdir, my_prefix);
27637
28172
  for (const my_match of the_subdir_matches) {
27638
28173
  if (!the_seen.has(my_match)) {
@@ -27670,14 +28205,14 @@ var init_indexer = __esm(() => {
27670
28205
  }
27671
28206
  let the_entries;
27672
28207
  try {
27673
- the_entries = await fs9.promises.readdir(my_entry.path, {
28208
+ the_entries = await fs10.promises.readdir(my_entry.path, {
27674
28209
  withFileTypes: true
27675
28210
  });
27676
28211
  } catch {
27677
28212
  continue;
27678
28213
  }
27679
28214
  for (const my_dirent of the_entries) {
27680
- const my_path = path11.join(my_entry.path, my_dirent.name);
28215
+ const my_path = path12.join(my_entry.path, my_dirent.name);
27681
28216
  if (my_dirent.isDirectory()) {
27682
28217
  if (!WorkspaceIndexer.EXCLUDED_DIRS.has(my_dirent.name)) {
27683
28218
  the_dirs.push({
@@ -27687,7 +28222,7 @@ var init_indexer = __esm(() => {
27687
28222
  }
27688
28223
  continue;
27689
28224
  }
27690
- if (my_dirent.name === basename6 && await entry_is_file_async(my_dirent, my_path, fs9.promises)) {
28225
+ if (my_dirent.name === basename6 && await entry_is_file_async(my_dirent, my_path, fs10.promises)) {
27691
28226
  return my_path;
27692
28227
  }
27693
28228
  }
@@ -27696,9 +28231,9 @@ var init_indexer = __esm(() => {
27696
28231
  }
27697
28232
  resolve_program(name, referring_uri) {
27698
28233
  const referring_path = URI.parse(referring_uri).fsPath;
27699
- const current_dir = path11.dirname(referring_path);
27700
- const local_ado = path11.join(current_dir, `${name}.ado`);
27701
- if (fs9.existsSync(local_ado)) {
28234
+ const current_dir = path12.dirname(referring_path);
28235
+ const local_ado = path12.join(current_dir, `${name}.ado`);
28236
+ if (fs10.existsSync(local_ado)) {
27702
28237
  const local_uri = URI.file(local_ado).toString();
27703
28238
  const entry = this.symbol_index.get(local_uri);
27704
28239
  return entry?.symbols.programs.get(name);
@@ -27717,7 +28252,7 @@ var init_indexer = __esm(() => {
27717
28252
  }
27718
28253
  try {
27719
28254
  const file_path = URI.parse(file_uri).fsPath;
27720
- const content = await fs9.promises.readFile(file_path, "utf8");
28255
+ const content = await fs10.promises.readFile(file_path, "utf8");
27721
28256
  const resolve_config = build_scope_resolver_config(cross_file_config);
27722
28257
  const resolved_scope = await scope_resolver.resolve(file_uri, content, resolve_config);
27723
28258
  return resolved_scope.symbols;
@@ -28005,8 +28540,7 @@ class IndentationDiagnosticAnalyzer {
28005
28540
  }
28006
28541
  return;
28007
28542
  }
28008
- 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";
28009
- if (is_control_flow && node.body) {
28543
+ if (this.is_block_node_type(node) && "body" in node && node.body) {
28010
28544
  for (const child of node.body) {
28011
28545
  const child_start_line = child.range.start.line;
28012
28546
  if (child_start_line === start_line) {
@@ -28052,9 +28586,8 @@ class IndentationDiagnosticAnalyzer {
28052
28586
  }
28053
28587
  return;
28054
28588
  }
28055
- if (this.is_block_node_type(node)) {
28056
- const block_node = node;
28057
- for (const my_child of block_node.body) {
28589
+ if (this.is_block_node_type(node) && "body" in node && node.body) {
28590
+ for (const my_child of node.body) {
28058
28591
  const child_start_line = my_child.range.start.line;
28059
28592
  if (child_start_line === start_line) {
28060
28593
  walk_node(my_child, depth);
@@ -28067,6 +28600,10 @@ class IndentationDiagnosticAnalyzer {
28067
28600
  expected_depths.set(end_line, depth);
28068
28601
  }
28069
28602
  }
28603
+ } else if ("body" in node && node.body) {
28604
+ for (const my_child of node.body) {
28605
+ walk_node(my_child, depth);
28606
+ }
28070
28607
  }
28071
28608
  };
28072
28609
  for (const my_node of document.ast.nodes) {
@@ -28080,7 +28617,7 @@ class IndentationDiagnosticAnalyzer {
28080
28617
  return expected_depths;
28081
28618
  }
28082
28619
  is_block_node_type(node) {
28083
- return node.type === "program" || node.type === "if" || node.type === "else" || node.type === "foreach" || node.type === "forvalues" || node.type === "while" || node.type === "frame";
28620
+ return node.type === "program" || node.type === "if" && !node.is_single_statement || node.type === "else" || node.type === "foreach" || node.type === "forvalues" || node.type === "while" || node.type === "frame";
28084
28621
  }
28085
28622
  should_skip_unnecessary_check(line, lineIndex, block_comment_lines2, continuation_lines) {
28086
28623
  if (block_comment_lines2.has(lineIndex)) {
@@ -29712,6 +30249,7 @@ class DiagnosticsProvider {
29712
30249
  const backward_dep_mode = config.cross_file?.backward_dependencies ?? "auto";
29713
30250
  const scan_complete_for_deferral = resolved_scope?.scan_complete_at_resolve_time ?? false;
29714
30251
  const defer_undefined_diagnostics = backward_dep_mode === "auto" && this.dependency_graph && !scan_complete_for_deferral && resolved_scope && !resolved_scope.has_directives && !resolved_scope.has_auto_parents && !resolved_scope.is_standalone;
30252
+ const inherited_entry_locals = collect_inherited_dofile_locals(resolved_scope, 0, document.uri);
29715
30253
  for (const my_diagnostic of this.extract_semantic_diagnostics(document)) {
29716
30254
  if (this.is_in_embedded_context(my_diagnostic.range.start, the_context_ranges)) {
29717
30255
  continue;
@@ -29723,6 +30261,9 @@ class DiagnosticsProvider {
29723
30261
  const symbol_name = is_undefined_symbol ? this.extract_symbol_name_from_diagnostic(my_diagnostic) : null;
29724
30262
  const reference_kind = is_undefined_symbol ? this.classify_reference_kind(my_diagnostic) : null;
29725
30263
  if (resolved_scope && symbol_name) {
30264
+ if (reference_kind === "local" && inherited_entry_locals.has(symbol_name)) {
30265
+ continue;
30266
+ }
29726
30267
  if (this.is_symbol_defined_in_scope(symbol_name, resolved_scope.symbols, my_diagnostic.code, document.uri, reference_kind)) {
29727
30268
  continue;
29728
30269
  }
@@ -30437,6 +30978,7 @@ var init_diagnostics = __esm(() => {
30437
30978
  init_types2();
30438
30979
  init_types();
30439
30980
  init_scoped_locals();
30981
+ init_dofile_locals();
30440
30982
  init_scope_resolver();
30441
30983
  init_diagnostic_code_description();
30442
30984
  init_file_path_utils();
@@ -31497,8 +32039,8 @@ function format_help_link(topic, display) {
31497
32039
  }
31498
32040
 
31499
32041
  // src/providers/completion.ts
31500
- import * as fs10 from "fs";
31501
- import * as path12 from "path";
32042
+ import * as fs11 from "fs";
32043
+ import * as path13 from "path";
31502
32044
  function coerce_macro_map(value) {
31503
32045
  if (value instanceof Map) {
31504
32046
  return value;
@@ -32264,15 +32806,15 @@ class CompletionProvider {
32264
32806
  const path_parts = clean_path.split("/");
32265
32807
  search_prefix = path_parts.pop() || "";
32266
32808
  const dir_path = path_parts.join("/");
32267
- base_dir = path12.resolve(workspace_root, dir_path);
32809
+ base_dir = path13.resolve(workspace_root, dir_path);
32268
32810
  } else {
32269
32811
  search_prefix = clean_path;
32270
32812
  }
32271
32813
  }
32272
- if (!fs10.existsSync(base_dir) || !fs10.statSync(base_dir).isDirectory()) {
32814
+ if (!fs11.existsSync(base_dir) || !fs11.statSync(base_dir).isDirectory()) {
32273
32815
  return completions;
32274
32816
  }
32275
- const entries = fs10.readdirSync(base_dir, { withFileTypes: true });
32817
+ const entries = fs11.readdirSync(base_dir, { withFileTypes: true });
32276
32818
  for (const entry of entries) {
32277
32819
  if (entry.name.startsWith(".")) {
32278
32820
  continue;
@@ -32280,7 +32822,7 @@ class CompletionProvider {
32280
32822
  if (search_prefix && !entry.name.toLowerCase().startsWith(search_prefix.toLowerCase())) {
32281
32823
  continue;
32282
32824
  }
32283
- const entry_kind = classify_entry_sync(entry, path12.join(base_dir, entry.name), fs10);
32825
+ const entry_kind = classify_entry_sync(entry, path13.join(base_dir, entry.name), fs11);
32284
32826
  if (entry_kind === "directory") {
32285
32827
  completions.push({
32286
32828
  label: entry.name + "/",
@@ -32308,17 +32850,17 @@ class CompletionProvider {
32308
32850
  get_workspace_root(document_uri) {
32309
32851
  try {
32310
32852
  const file_path = document_uri.replace(/^file:\/\//, "");
32311
- let current_dir = path12.dirname(file_path);
32312
- while (current_dir !== path12.dirname(current_dir)) {
32853
+ let current_dir = path13.dirname(file_path);
32854
+ while (current_dir !== path13.dirname(current_dir)) {
32313
32855
  const markers = [".git", "sight.toml", ".sight.json", "package.json", ".vscode"];
32314
32856
  for (const marker of markers) {
32315
- if (fs10.existsSync(path12.join(current_dir, marker))) {
32857
+ if (fs11.existsSync(path13.join(current_dir, marker))) {
32316
32858
  return current_dir;
32317
32859
  }
32318
32860
  }
32319
- current_dir = path12.dirname(current_dir);
32861
+ current_dir = path13.dirname(current_dir);
32320
32862
  }
32321
- return path12.dirname(file_path);
32863
+ return path13.dirname(file_path);
32322
32864
  } catch {
32323
32865
  return null;
32324
32866
  }
@@ -33576,7 +34118,7 @@ var init_help_resolver = __esm(() => {
33576
34118
  });
33577
34119
 
33578
34120
  // src/server-handlers.ts
33579
- import * as fs11 from "fs";
34121
+ import * as fs12 from "fs";
33580
34122
  function create_initialize_handler(on_capabilities_detected, on_initialization_options_detected, on_root_uri_detected) {
33581
34123
  return (params) => {
33582
34124
  const capabilities = params.capabilities;
@@ -33803,7 +34345,7 @@ function create_shutdown_handler(deps, disposables) {
33803
34345
  const SHUTDOWN_TIMEOUT_MS = 500;
33804
34346
  await Promise.race([
33805
34347
  deps.document_store.dispose(),
33806
- new Promise((resolve11) => setTimeout(resolve11, SHUTDOWN_TIMEOUT_MS))
34348
+ new Promise((resolve12) => setTimeout(resolve12, SHUTDOWN_TIMEOUT_MS))
33807
34349
  ]);
33808
34350
  }
33809
34351
  deps?.scope_resolver?.dispose();
@@ -33820,10 +34362,14 @@ function create_exit_handler(on_exit) {
33820
34362
  }
33821
34363
  };
33822
34364
  }
33823
- function create_did_change_watched_files_handler(deps, parse_uri, on_file_changed, on_project_config_changed) {
34365
+ function create_did_change_watched_files_handler(deps, parse_uri, on_file_changed, on_project_config_changed, on_gitignore_changed) {
33824
34366
  return (params) => {
33825
34367
  for (const my_event of params.changes) {
33826
34368
  const file_path = parse_uri(my_event.uri);
34369
+ if (GITIGNORE_PATH.test(file_path)) {
34370
+ on_gitignore_changed?.(my_event.uri);
34371
+ continue;
34372
+ }
33827
34373
  if (is_project_config_event_path(file_path)) {
33828
34374
  on_project_config_changed?.(my_event.uri);
33829
34375
  continue;
@@ -33906,7 +34452,7 @@ function create_shared_ihlp_resolver(deps, max_size = MAX_IHLP_CACHE_SIZE) {
33906
34452
  const my_cached = the_cache.get(my_path);
33907
34453
  if (my_cached !== undefined) {
33908
34454
  try {
33909
- const my_stat = await fs11.promises.stat(my_path);
34455
+ const my_stat = await fs12.promises.stat(my_path);
33910
34456
  if (my_stat.mtimeMs === my_cached.mtime_ms) {
33911
34457
  the_cache.delete(my_path);
33912
34458
  the_cache.set(my_path, my_cached);
@@ -33919,8 +34465,8 @@ function create_shared_ihlp_resolver(deps, max_size = MAX_IHLP_CACHE_SIZE) {
33919
34465
  }
33920
34466
  }
33921
34467
  try {
33922
- const my_stat = await fs11.promises.stat(my_path);
33923
- const my_content = await fs11.promises.readFile(my_path, "utf-8");
34468
+ const my_stat = await fs12.promises.stat(my_path);
34469
+ const my_content = await fs12.promises.readFile(my_path, "utf-8");
33924
34470
  if (the_cache.size >= max_size) {
33925
34471
  const my_first = the_cache.keys().next().value;
33926
34472
  if (my_first !== undefined) {
@@ -33957,7 +34503,7 @@ function create_resolve_sthlp_file_handler(deps, shared_ihlp) {
33957
34503
  if (!deps.workspace_indexer)
33958
34504
  return null;
33959
34505
  try {
33960
- const my_content = await fs11.promises.readFile(file_path, "utf-8");
34506
+ const my_content = await fs12.promises.readFile(file_path, "utf-8");
33961
34507
  return await expand_includes(my_content, my_ihlp_resolver);
33962
34508
  } catch {
33963
34509
  return null;
@@ -34036,7 +34582,7 @@ function create_expand_includes_handler(deps, shared_ihlp) {
34036
34582
  return { content: my_result };
34037
34583
  };
34038
34584
  }
34039
- var import_node7, DEFAULT_SETTINGS, MAX_IHLP_CACHE_SIZE = 500, MAX_RESOLVE_STHLP_NEGATIVE_CACHE_SIZE = 1000;
34585
+ var import_node7, DEFAULT_SETTINGS, GITIGNORE_PATH, MAX_IHLP_CACHE_SIZE = 500, MAX_RESOLVE_STHLP_NEGATIVE_CACHE_SIZE = 1000;
34040
34586
  var init_server_handlers = __esm(() => {
34041
34587
  init_completion();
34042
34588
  init_context_tracker();
@@ -34085,6 +34631,9 @@ var init_server_handlers = __esm(() => {
34085
34631
  adoPaths: [],
34086
34632
  indexWorkspace: true,
34087
34633
  exclude: [],
34634
+ workspace: {
34635
+ respectGitignore: true
34636
+ },
34088
34637
  cross_file: {
34089
34638
  index_workspace: true,
34090
34639
  max_indexed_files: 1000,
@@ -34105,6 +34654,7 @@ var init_server_handlers = __esm(() => {
34105
34654
  },
34106
34655
  debug: false
34107
34656
  };
34657
+ GITIGNORE_PATH = /(?:^|[/\\])\.gitignore$/;
34108
34658
  });
34109
34659
 
34110
34660
  // src/utils/config-validator.ts
@@ -34246,6 +34796,13 @@ function validate_comment_formatting_config(config, log_warning) {
34246
34796
  if (typeof config.indexWorkspace === "boolean") {
34247
34797
  validated_config.indexWorkspace = config.indexWorkspace;
34248
34798
  }
34799
+ if (config.workspace?.respectGitignore !== undefined) {
34800
+ if (typeof config.workspace.respectGitignore === "boolean") {
34801
+ validated_config.workspace.respectGitignore = config.workspace.respectGitignore;
34802
+ } else {
34803
+ log_warning?.("Invalid workspace.respectGitignore: " + `${config.workspace.respectGitignore}. ` + "Using default: " + `${DEFAULT_SETTINGS.workspace.respectGitignore}`);
34804
+ }
34805
+ }
34249
34806
  if (typeof config.debug === "boolean") {
34250
34807
  validated_config.debug = config.debug;
34251
34808
  }
@@ -34557,46 +35114,50 @@ var init_shared = __esm(() => {
34557
35114
  });
34558
35115
 
34559
35116
  // src/cli/source-files.ts
34560
- import * as fs12 from "fs";
34561
- import * as path13 from "path";
35117
+ import * as fs13 from "fs";
35118
+ import * as path14 from "path";
34562
35119
  import { TextDecoder } from "util";
34563
35120
  function canonicalize_existing_path(file_path) {
34564
- return fs12.realpathSync.native(file_path);
35121
+ return fs13.realpathSync.native(file_path);
34565
35122
  }
34566
35123
  function workspace_relative(workspace_root, file_path) {
34567
- const relative6 = path13.relative(workspace_root, file_path);
34568
- const inside = relative6 !== ".." && !relative6.startsWith(`..${path13.sep}`) && !path13.isAbsolute(relative6);
34569
- return { relative: relative6, inside };
35124
+ const relative7 = path14.relative(workspace_root, file_path);
35125
+ const inside = relative7 !== ".." && !relative7.startsWith(`..${path14.sep}`) && !path14.isAbsolute(relative7);
35126
+ return { relative: relative7, inside };
34570
35127
  }
34571
35128
  function relative_path(workspace_root, file_path) {
34572
- const { relative: relative6 } = workspace_relative(workspace_root, file_path);
34573
- if (relative6 === "") {
35129
+ const { relative: relative7 } = workspace_relative(workspace_root, file_path);
35130
+ if (relative7 === "") {
34574
35131
  return ".";
34575
35132
  }
34576
- return path13.isAbsolute(relative6) ? file_path : relative6.split(path13.sep).join("/");
35133
+ return path14.isAbsolute(relative7) ? file_path : relative7.split(path14.sep).join("/");
34577
35134
  }
34578
35135
  function is_within_workspace(workspace_root, file_path) {
34579
- const { relative: relative6, inside } = workspace_relative(workspace_root, file_path);
34580
- return relative6 === "" || relative6.length > 0 && inside;
35136
+ const { relative: relative7, inside } = workspace_relative(workspace_root, file_path);
35137
+ return relative7 === "" || relative7.length > 0 && inside;
34581
35138
  }
34582
- function walk_sources(dir_path, out, operator_errors, workspace_roots, exclude_matcher) {
35139
+ function walk_sources(dir_path, out, operator_errors, workspace_roots, exclude_matcher, gitignore_matcher) {
35140
+ if (gitignore_matcher.is_ignored(dir_path, "directory"))
35141
+ return;
34583
35142
  let entries;
34584
35143
  try {
34585
- entries = fs12.readdirSync(dir_path, { withFileTypes: true });
35144
+ entries = fs13.readdirSync(dir_path, { withFileTypes: true });
34586
35145
  } catch (error) {
34587
35146
  operator_errors.push(`cannot read directory: ${dir_path}: ${error_message(error)}`);
34588
35147
  return;
34589
35148
  }
34590
35149
  for (const entry of entries) {
34591
- const entry_path = path13.join(dir_path, entry.name);
35150
+ const entry_path = path14.join(dir_path, entry.name);
34592
35151
  if (entry.isDirectory()) {
34593
35152
  if (entry.name.startsWith("."))
34594
35153
  continue;
34595
35154
  if (!exclude_matcher.is_empty && exclude_matcher.is_excluded_dir(entry_path, workspace_roots)) {
34596
35155
  continue;
34597
35156
  }
34598
- walk_sources(entry_path, out, operator_errors, workspace_roots, exclude_matcher);
35157
+ walk_sources(entry_path, out, operator_errors, workspace_roots, exclude_matcher, gitignore_matcher);
34599
35158
  } else if (entry.isFile() && hasStataExtension(entry.name)) {
35159
+ if (gitignore_matcher.is_ignored(entry_path, "file"))
35160
+ continue;
34600
35161
  if (!exclude_matcher.is_empty && exclude_matcher.is_excluded_file(entry_path, workspace_roots)) {
34601
35162
  continue;
34602
35163
  }
@@ -34604,20 +35165,21 @@ function walk_sources(dir_path, out, operator_errors, workspace_roots, exclude_m
34604
35165
  }
34605
35166
  }
34606
35167
  }
34607
- function collect_report_targets(input_paths, workspace_root, cwd, exclude_patterns = []) {
35168
+ function collect_report_targets(input_paths, workspace_root, cwd, exclude_patterns = [], respect_gitignore = true) {
34608
35169
  const operator_errors = [];
34609
35170
  const source_paths = [];
34610
- let normalized_root = path13.resolve(workspace_root);
35171
+ let normalized_root = path14.resolve(workspace_root);
34611
35172
  try {
34612
35173
  normalized_root = canonicalize_existing_path(normalized_root);
34613
35174
  } catch {}
34614
35175
  const exclude_matcher = create_exclude_matcher(exclude_patterns);
34615
35176
  const exclude_roots = [normalized_root];
35177
+ const gitignore_matcher = create_gitignore_matcher(exclude_roots, respect_gitignore);
34616
35178
  const has_explicit_paths = input_paths.length > 0;
34617
35179
  const paths_to_collect = input_paths.length > 0 ? input_paths : [normalized_root];
34618
35180
  for (const input_path of paths_to_collect) {
34619
- const resolved_path = path13.resolve(cwd, input_path);
34620
- if (!fs12.existsSync(resolved_path)) {
35181
+ const resolved_path = path14.resolve(cwd, input_path);
35182
+ if (!fs13.existsSync(resolved_path)) {
34621
35183
  operator_errors.push(`path does not exist: ${input_path}`);
34622
35184
  continue;
34623
35185
  }
@@ -34630,13 +35192,13 @@ function collect_report_targets(input_paths, workspace_root, cwd, exclude_patter
34630
35192
  }
34631
35193
  let stat;
34632
35194
  try {
34633
- stat = fs12.statSync(absolute_path);
35195
+ stat = fs13.statSync(absolute_path);
34634
35196
  } catch (error) {
34635
35197
  operator_errors.push(`cannot stat path: ${input_path}: ${error_message(error)}`);
34636
35198
  continue;
34637
35199
  }
34638
35200
  if (stat.isDirectory()) {
34639
- walk_sources(absolute_path, source_paths, operator_errors, exclude_roots, exclude_matcher);
35201
+ walk_sources(absolute_path, source_paths, operator_errors, exclude_roots, exclude_matcher, gitignore_matcher);
34640
35202
  } else if (stat.isFile() && hasStataExtension(absolute_path)) {
34641
35203
  source_paths.push(absolute_path);
34642
35204
  }
@@ -34725,7 +35287,7 @@ function decode_error_diagnostic(offset) {
34725
35287
  function read_source_file(file_path) {
34726
35288
  let bytes;
34727
35289
  try {
34728
- bytes = fs12.readFileSync(file_path);
35290
+ bytes = fs13.readFileSync(file_path);
34729
35291
  } catch (error) {
34730
35292
  return {
34731
35293
  kind: "read-error",
@@ -34749,6 +35311,7 @@ var init_source_files = __esm(() => {
34749
35311
  init_file_path_utils();
34750
35312
  init_exclude_matcher();
34751
35313
  init_diagnostic_code_description();
35314
+ init_gitignore_matcher();
34752
35315
  init_shared();
34753
35316
  import_vscode_languageserver6 = __toESM(require_main4(), 1);
34754
35317
  });
@@ -34763,8 +35326,8 @@ __export(exports_check, {
34763
35326
  collect_check_diagnostics: () => collect_check_diagnostics,
34764
35327
  build_check_context: () => build_check_context
34765
35328
  });
34766
- import * as fs13 from "fs";
34767
- import * as path14 from "path";
35329
+ import * as fs14 from "fs";
35330
+ import * as path15 from "path";
34768
35331
  function parse_required_option_value(argv, index, flag, value_kind, inline_value) {
34769
35332
  if (inline_value !== undefined) {
34770
35333
  if (inline_value.length === 0) {
@@ -34930,7 +35493,7 @@ function load_check_config(options) {
34930
35493
  warnings: validation_warnings
34931
35494
  };
34932
35495
  }
34933
- const loaded = options.config_path ? load_toml_file(path14.resolve(options.cwd, options.config_path)) : discover_and_load_project_config(options.workspace_root);
35496
+ const loaded = options.config_path ? load_toml_file(path15.resolve(options.cwd, options.config_path)) : discover_and_load_project_config(options.workspace_root);
34934
35497
  if (loaded.kind === "load-failed") {
34935
35498
  return {
34936
35499
  kind: "operator-error",
@@ -35026,7 +35589,7 @@ async function collect_check_diagnostics(context, workspace_root, config, target
35026
35589
  const uri = URI.file(target.path).toString();
35027
35590
  let stats;
35028
35591
  try {
35029
- stats = fs13.statSync(target.path);
35592
+ stats = fs14.statSync(target.path);
35030
35593
  } catch (error) {
35031
35594
  records.push(diagnostic_record(target.relative_path, unreadable_diagnostic(read_error_detail(error))));
35032
35595
  return records;
@@ -35037,7 +35600,7 @@ async function collect_check_diagnostics(context, workspace_root, config, target
35037
35600
  }
35038
35601
  return records;
35039
35602
  }
35040
- if (is_within_workspace(workspace_root, target.path) && files_indexed >= config.cross_file.max_indexed_files && !context.workspace_indexer.has_indexed_file(uri) && !is_hidden_source_path(target.path, scan_roots) && !exclude_matcher.is_excluded_file(target.path, [workspace_root])) {
35603
+ if (is_within_workspace(workspace_root, target.path) && files_indexed >= config.cross_file.max_indexed_files && !context.workspace_indexer.has_indexed_file(uri) && !context.workspace_indexer.is_gitignored(target.path) && !is_hidden_source_path(target.path, scan_roots) && !exclude_matcher.is_excluded_file(target.path, [workspace_root])) {
35041
35604
  records.push(diagnostic_record(target.relative_path, index_limit_diagnostic()));
35042
35605
  return records;
35043
35606
  }
@@ -35121,10 +35684,10 @@ async function run_check_with_cwd(argv, cwd, output = DEFAULT_OUTPUT) {
35121
35684
  `);
35122
35685
  return EXIT_OK;
35123
35686
  }
35124
- const resolved_workspace_root = path14.resolve(cwd, result.args.workspace ?? ".");
35687
+ const resolved_workspace_root = path15.resolve(cwd, result.args.workspace ?? ".");
35125
35688
  let is_workspace_directory = false;
35126
35689
  try {
35127
- is_workspace_directory = fs13.statSync(resolved_workspace_root).isDirectory();
35690
+ is_workspace_directory = fs14.statSync(resolved_workspace_root).isDirectory();
35128
35691
  } catch {
35129
35692
  is_workspace_directory = false;
35130
35693
  }
@@ -35156,7 +35719,7 @@ async function run_check_with_cwd(argv, cwd, output = DEFAULT_OUTPUT) {
35156
35719
  `);
35157
35720
  return EXIT_OPERATOR_ERROR;
35158
35721
  }
35159
- const target_result = collect_report_targets(result.args.paths, workspace_root, cwd, config_result.config.exclude);
35722
+ const target_result = collect_report_targets(result.args.paths, workspace_root, cwd, config_result.config.exclude, config_result.config.workspace.respectGitignore);
35160
35723
  if (target_result.operator_errors.length > 0) {
35161
35724
  for (const message of target_result.operator_errors) {
35162
35725
  output.stderr(`sight check: ${message}
@@ -35485,7 +36048,7 @@ function is_position_in_range3(position, range) {
35485
36048
  }
35486
36049
 
35487
36050
  // src/providers/hover.ts
35488
- import * as path15 from "path";
36051
+ import * as path16 from "path";
35489
36052
  function has_definition_index(hit) {
35490
36053
  return typeof hit.definition_index === "number";
35491
36054
  }
@@ -36835,7 +37398,7 @@ ${source_info}${footer}`
36835
37398
  if (this.looks_like_uri_scheme(uri_or_path)) {
36836
37399
  return null;
36837
37400
  }
36838
- return path15.resolve(uri_or_path);
37401
+ return path16.resolve(uri_or_path);
36839
37402
  }
36840
37403
  escape_markdown_link_text(text) {
36841
37404
  return text.replace(/[\\[\]()]/g, "\\$&");
@@ -36855,11 +37418,11 @@ ${source_info}${footer}`
36855
37418
  if (workspace_fs_path === null) {
36856
37419
  return fs_path;
36857
37420
  }
36858
- const relative7 = path15.relative(workspace_fs_path, fs_path);
36859
- if (relative7.startsWith("..") || path15.isAbsolute(relative7)) {
37421
+ const relative8 = path16.relative(workspace_fs_path, fs_path);
37422
+ if (relative8.startsWith("..") || path16.isAbsolute(relative8)) {
36860
37423
  return fs_path;
36861
37424
  }
36862
- return relative7;
37425
+ return relative8;
36863
37426
  }
36864
37427
  format_source_link(source_uri, current_uri, workspace_root) {
36865
37428
  const source_path = this.normalize_file_path(source_uri);
@@ -37210,7 +37773,7 @@ var init_hover = __esm(() => {
37210
37773
  });
37211
37774
 
37212
37775
  // src/providers/definition.ts
37213
- import * as path16 from "path";
37776
+ import * as path17 from "path";
37214
37777
 
37215
37778
  class DefinitionProvider {
37216
37779
  workspace_roots = [];
@@ -37955,7 +38518,7 @@ class DefinitionProvider {
37955
38518
  if (!the_call) {
37956
38519
  return { matched: false, path: null };
37957
38520
  }
37958
- const current_dir = path16.dirname(URI.parse(document.uri).fsPath);
38521
+ const current_dir = path17.dirname(URI.parse(document.uri).fsPath);
37959
38522
  const my_outcome = resolve_forward_call_rich(file_path, current_dir, the_call.working_directory, { workspace_roots: this.workspace_roots });
37960
38523
  if (my_outcome.kind === "exact" || my_outcome.kind === "case_only") {
37961
38524
  return { matched: true, path: my_outcome.path };
@@ -37964,8 +38527,8 @@ class DefinitionProvider {
37964
38527
  }
37965
38528
  resolve_file_path(current_uri, file_path) {
37966
38529
  const current_path = URI.parse(current_uri).fsPath;
37967
- const current_dir = path16.dirname(current_path);
37968
- const resolved_path = path16.resolve(current_dir, file_path);
38530
+ const current_dir = path17.dirname(current_path);
38531
+ const resolved_path = path17.resolve(current_dir, file_path);
37969
38532
  const the_roots_set = new Set(this.workspace_roots);
37970
38533
  the_roots_set.add(current_dir);
37971
38534
  const the_roots = Array.from(the_roots_set);
@@ -38539,7 +39102,7 @@ class ReferencesProvider {
38539
39102
  }
38540
39103
  file_count++;
38541
39104
  if (file_count % 10 === 0) {
38542
- await new Promise((resolve15) => setTimeout(resolve15, 0));
39105
+ await new Promise((resolve16) => setTimeout(resolve16, 0));
38543
39106
  if (cancellation_token?.isCancellationRequested) {
38544
39107
  break;
38545
39108
  }
@@ -38965,7 +39528,7 @@ var init_section_detector = __esm(() => {
38965
39528
  });
38966
39529
 
38967
39530
  // src/providers/symbols.ts
38968
- import * as path17 from "path";
39531
+ import * as path18 from "path";
38969
39532
  function is_position_in_range4(position, range) {
38970
39533
  if (position.line < range.start.line) {
38971
39534
  return false;
@@ -39361,7 +39924,7 @@ class SymbolProvider {
39361
39924
  }
39362
39925
  }
39363
39926
  for (const document of all_documents) {
39364
- const my_basename = path17.basename(document.uri);
39927
+ const my_basename = path18.basename(document.uri);
39365
39928
  for (const my_program of document.symbols.programs.values()) {
39366
39929
  if (my_program.name.toLowerCase().includes(lower_query)) {
39367
39930
  symbols.push({
@@ -39618,6 +40181,13 @@ class IndentationAnalyzer {
39618
40181
  this.process_embedded_block_node(node);
39619
40182
  return;
39620
40183
  }
40184
+ if (node.type === "if" && node.is_single_statement) {
40185
+ this.process_regular_node(node);
40186
+ for (const my_child of node.body) {
40187
+ this.walk_node(my_child);
40188
+ }
40189
+ return;
40190
+ }
39621
40191
  if (this.is_block_node(node)) {
39622
40192
  if (node.type === "command") {
39623
40193
  const cmd = node;
@@ -41292,6 +41862,12 @@ class PrettyPrinter {
41292
41862
  return spaced.replace(/\(\s+/g, "(").replace(/\s+\)/g, ")");
41293
41863
  }
41294
41864
  printControlFlow(node) {
41865
+ if (node.type === "if" && node.is_single_statement) {
41866
+ const body_node = node.body[0];
41867
+ const body = body_node ? this.printNode(body_node) : "";
41868
+ const inline_body = body.trimStart().slice(0, -this.getStatementTerminator().length);
41869
+ return `${this.getIndent()}if ${node.condition || ""} ${inline_body}`;
41870
+ }
41295
41871
  const the_lines = [];
41296
41872
  let header = this.getIndent();
41297
41873
  switch (node.type) {
@@ -41334,7 +41910,7 @@ class PrettyPrinter {
41334
41910
  }
41335
41911
  printEmbeddedBlock(node) {
41336
41912
  if (node.is_single_line) {
41337
- return `${this.getIndent()}${node.start_command} ${node.content}${this.getStatementTerminator()}`;
41913
+ return `${this.getIndent()}${node.start_command} ${node.content}`;
41338
41914
  }
41339
41915
  const the_lines = [];
41340
41916
  the_lines.push(`${this.getIndent()}${node.start_command}`);
@@ -41806,8 +42382,8 @@ class DocumentDebounceManager {
41806
42382
  if (prev_resolver) {
41807
42383
  prev_resolver();
41808
42384
  }
41809
- const promise = new Promise((resolve15) => {
41810
- this.pending_resolvers.set(uri, resolve15);
42385
+ const promise = new Promise((resolve16) => {
42386
+ this.pending_resolvers.set(uri, resolve16);
41811
42387
  });
41812
42388
  this.pending_promises.set(uri, promise);
41813
42389
  const timer = setTimeout(() => {
@@ -41833,9 +42409,9 @@ class DocumentDebounceManager {
41833
42409
  if (this.parse_queue.length >= this.MAX_QUEUE_LENGTH) {
41834
42410
  logger.warn(`Parse queue full, dropping ${uri} v${version}`);
41835
42411
  this.metrics.dropped_parses++;
41836
- const resolve15 = this.pending_resolvers.get(uri);
41837
- if (resolve15) {
41838
- resolve15();
42412
+ const resolve16 = this.pending_resolvers.get(uri);
42413
+ if (resolve16) {
42414
+ resolve16();
41839
42415
  this.pending_resolvers.delete(uri);
41840
42416
  this.pending_promises.delete(uri);
41841
42417
  }
@@ -41858,7 +42434,7 @@ class DocumentDebounceManager {
41858
42434
  }
41859
42435
  this.active_parses++;
41860
42436
  try {
41861
- await new Promise((resolve15) => setImmediate(resolve15));
42437
+ await new Promise((resolve16) => setImmediate(resolve16));
41862
42438
  await callback();
41863
42439
  } catch (error) {
41864
42440
  logger.error(`Parse error for ${uri}: ${error}`);
@@ -41890,9 +42466,9 @@ class DocumentDebounceManager {
41890
42466
  clearTimeout(existing);
41891
42467
  this.pending_timers.delete(uri);
41892
42468
  }
41893
- const resolve15 = this.pending_resolvers.get(uri);
41894
- if (resolve15) {
41895
- resolve15();
42469
+ const resolve16 = this.pending_resolvers.get(uri);
42470
+ if (resolve16) {
42471
+ resolve16();
41896
42472
  this.pending_resolvers.delete(uri);
41897
42473
  this.pending_promises.delete(uri);
41898
42474
  }
@@ -72714,7 +73290,8 @@ __export(exports_server_factory, {
72714
73290
  create_server: () => create_server,
72715
73291
  build_non_capability_settings_from_sources: () => build_non_capability_settings_from_sources
72716
73292
  });
72717
- import * as fs14 from "fs";
73293
+ import * as fs15 from "fs";
73294
+ import * as path19 from "path";
72718
73295
  function create_transport_connection(transport) {
72719
73296
  if (transport === "stdio") {
72720
73297
  return import_node8.createConnection(process.stdin, process.stdout);
@@ -72750,6 +73327,7 @@ function indexing_affecting_signature(config) {
72750
73327
  return JSON.stringify({
72751
73328
  adoPaths: config?.adoPaths ?? null,
72752
73329
  exclude: config?.exclude ?? null,
73330
+ respectGitignore: config?.workspace?.respectGitignore ?? true,
72753
73331
  indexWorkspace: config?.indexWorkspace ?? null,
72754
73332
  index_workspace: config?.cross_file?.index_workspace ?? null,
72755
73333
  max_indexed_files: config?.cross_file?.max_indexed_files ?? null,
@@ -72792,6 +73370,13 @@ async function create_server(options) {
72792
73370
  let project_config_candidate_dirs = [];
72793
73371
  let active_workspace_roots = [];
72794
73372
  let project_config_watch_registration = undefined;
73373
+ let gitignore_watch_registration;
73374
+ let gitignore_watch_seq = 0;
73375
+ let gitignore_watch_directories = [];
73376
+ let gitignore_refresh_pending = false;
73377
+ let gitignore_refresh_scheduled = false;
73378
+ let gitignore_change_seq = 0;
73379
+ let workspace_indexing_seq = 0;
72795
73380
  let last_applied_indexing_signature = "";
72796
73381
  let config_change_seq = 0;
72797
73382
  let init_options_config = undefined;
@@ -72893,6 +73478,65 @@ async function create_server(options) {
72893
73478
  }
72894
73479
  previous_registration?.dispose();
72895
73480
  }
73481
+ async function refresh_gitignore_watchers() {
73482
+ const my_seq = ++gitignore_watch_seq;
73483
+ if (!server_capabilities.has_watched_files_dynamic_registration_capability) {
73484
+ return;
73485
+ }
73486
+ const watchers = gitignore_watch_directories.map(({ directory, recursive }) => ({
73487
+ globPattern: {
73488
+ baseUri: URI.file(directory).toString(),
73489
+ pattern: recursive ? "**/.gitignore" : ".gitignore"
73490
+ },
73491
+ kind: import_node8.WatchKind.Create | import_node8.WatchKind.Change | import_node8.WatchKind.Delete
73492
+ }));
73493
+ const registration = watchers.length > 0 ? await connection.client.register(import_node8.DidChangeWatchedFilesNotification.type, { watchers }) : undefined;
73494
+ if (my_seq !== gitignore_watch_seq || shutdown_requested) {
73495
+ registration?.dispose();
73496
+ return;
73497
+ }
73498
+ const previous_registration = gitignore_watch_registration;
73499
+ gitignore_watch_registration = registration;
73500
+ previous_registration?.dispose();
73501
+ }
73502
+ function is_relevant_gitignore(uri) {
73503
+ const directory = path19.dirname(URI.parse(uri).fsPath);
73504
+ return gitignore_watch_directories.some((watch) => {
73505
+ const relative9 = path19.relative(watch.directory, directory);
73506
+ return relative9 === "" || watch.recursive && relative9 !== ".." && !relative9.startsWith(`..${path19.sep}`) && !path19.isAbsolute(relative9);
73507
+ });
73508
+ }
73509
+ function schedule_gitignore_refresh() {
73510
+ if (gitignore_refresh_scheduled || shutdown_requested)
73511
+ return;
73512
+ gitignore_refresh_scheduled = true;
73513
+ queueMicrotask(() => {
73514
+ const my_change_seq = gitignore_change_seq;
73515
+ const my_config_seq = config_change_seq;
73516
+ get_document_settings("").then((settings) => {
73517
+ if (shutdown_requested || !gitignore_refresh_pending || my_change_seq !== gitignore_change_seq || my_config_seq !== config_change_seq) {
73518
+ return;
73519
+ }
73520
+ configure_workspace_indexing(settings, active_workspace_roots, true);
73521
+ }).catch((error) => {
73522
+ connection.console.log(`[indexer] Gitignore refresh failed: ${error_message(error)}`);
73523
+ }).finally(() => {
73524
+ gitignore_refresh_scheduled = false;
73525
+ if (gitignore_refresh_pending && (my_change_seq !== gitignore_change_seq || my_config_seq !== config_change_seq)) {
73526
+ schedule_gitignore_refresh();
73527
+ }
73528
+ });
73529
+ });
73530
+ }
73531
+ function on_gitignore_changed(uri) {
73532
+ if (shutdown_requested || !is_relevant_gitignore(uri))
73533
+ return;
73534
+ gitignore_refresh_pending = true;
73535
+ gitignore_change_seq++;
73536
+ workspace_indexing_seq++;
73537
+ workspace_indexer?.cancel();
73538
+ schedule_gitignore_refresh();
73539
+ }
72896
73540
  function build_non_capability_settings() {
72897
73541
  return build_non_capability_settings_from_sources({
72898
73542
  init_options_config,
@@ -73101,10 +73745,16 @@ async function create_server(options) {
73101
73745
  scope_resolver?.reset_reverse_deps();
73102
73746
  }
73103
73747
  function configure_workspace_indexing(settings, folder_paths, reset_indexes) {
73748
+ const my_indexing_seq = ++workspace_indexing_seq;
73749
+ gitignore_refresh_pending = false;
73104
73750
  if (reset_indexes) {
73105
73751
  reset_workspace_indexing_state();
73106
73752
  }
73107
73753
  last_applied_indexing_signature = indexing_affecting_signature(settings);
73754
+ gitignore_watch_directories = create_gitignore_matcher(folder_paths, settings.workspace.respectGitignore).watch_directories;
73755
+ refresh_gitignore_watchers().catch((error) => {
73756
+ connection.console.log(`[indexer] Gitignore watcher registration failed: ` + error_message(error));
73757
+ });
73108
73758
  configure_completion_provider(settings);
73109
73759
  apply_cache_capacities(settings);
73110
73760
  if (workspace_indexer) {
@@ -73112,8 +73762,13 @@ async function create_server(options) {
73112
73762
  workspace_indexer.set_max_indexed_files(settings.cross_file?.max_indexed_files ?? 1000);
73113
73763
  }
73114
73764
  const indexing_enabled = settings.indexWorkspace !== false && settings.cross_file?.index_workspace !== false;
73115
- if (indexing_enabled && workspace_indexer && folder_paths.length > 0) {
73765
+ if (workspace_indexer && folder_paths.length > 0) {
73766
+ if (!indexing_enabled) {
73767
+ workspace_indexer.set_help_search_paths(discover_stata_ado_paths());
73768
+ }
73116
73769
  workspace_indexer.initialize(folder_paths, settings.adoPaths || []).then(() => {
73770
+ if (my_indexing_seq !== workspace_indexing_seq || shutdown_requested)
73771
+ return;
73117
73772
  resolve_sthlp_handler?.clear_negative_cache();
73118
73773
  if (dependency_graph?.is_scan_complete()) {
73119
73774
  revalidate_all_open_docs();
@@ -73155,7 +73810,7 @@ async function create_server(options) {
73155
73810
  global_settings = build_non_capability_settings();
73156
73811
  }
73157
73812
  const settings = await get_document_settings("");
73158
- const indexing_changed = indexing_affecting_signature(settings) !== last_applied_indexing_signature;
73813
+ const indexing_changed = gitignore_refresh_pending || indexing_affecting_signature(settings) !== last_applied_indexing_signature;
73159
73814
  if (indexing_changed) {
73160
73815
  configure_workspace_indexing(settings, active_workspace_roots, true);
73161
73816
  } else {
@@ -73410,14 +74065,14 @@ ${scope_resolver.get_reverse_deps_debug_info()}`);
73410
74065
  return open_doc.getText();
73411
74066
  }
73412
74067
  const fs_path = URI.parse(uri).fsPath;
73413
- return fs14.promises.readFile(fs_path, "utf8");
74068
+ return fs15.promises.readFile(fs_path, "utf8");
73414
74069
  },
73415
74070
  exists: async (uri) => {
73416
74071
  if (documents.get(uri))
73417
74072
  return true;
73418
74073
  const fs_path = URI.parse(uri).fsPath;
73419
74074
  try {
73420
- await fs14.promises.access(fs_path);
74075
+ await fs15.promises.access(fs_path);
73421
74076
  return true;
73422
74077
  } catch {
73423
74078
  return false;
@@ -73499,7 +74154,7 @@ ${scope_resolver.get_reverse_deps_debug_info()}`);
73499
74154
  }));
73500
74155
  function apply_runtime_settings_change(settings) {
73501
74156
  const new_signature = indexing_affecting_signature(settings);
73502
- if (new_signature !== last_applied_indexing_signature) {
74157
+ if (gitignore_refresh_pending || new_signature !== last_applied_indexing_signature) {
73503
74158
  configure_workspace_indexing(settings, active_workspace_roots, true);
73504
74159
  } else {
73505
74160
  configure_completion_provider(settings);
@@ -73575,6 +74230,9 @@ ${scope_resolver.get_reverse_deps_debug_info()}`);
73575
74230
  }
73576
74231
  if (dependency_graph) {
73577
74232
  const affected_callees = new Set(dependency_graph.get_callees(e.document.uri));
74233
+ if (workspace_indexer?.is_gitignored(URI.parse(e.document.uri).fsPath)) {
74234
+ dependency_graph.remove_caller(e.document.uri);
74235
+ }
73578
74236
  if (affected_callees.size > 0) {
73579
74237
  invalidate_and_revalidate_callees(affected_callees);
73580
74238
  }
@@ -73596,7 +74254,7 @@ ${scope_resolver.get_reverse_deps_debug_info()}`);
73596
74254
  }
73597
74255
  }, async () => {
73598
74256
  await reload_project_config_from_active_root();
73599
- }));
74257
+ }, on_gitignore_changed));
73600
74258
  connection.onNotification(DIAGNOSTIC_RESOURCES_CHANGED_NOTIFICATION, (params) => {
73601
74259
  const next = diagnostic_uris_from_notification(params);
73602
74260
  if (next !== undefined) {
@@ -73631,6 +74289,9 @@ ${scope_resolver.get_reverse_deps_debug_info()}`);
73631
74289
  });
73632
74290
  connection.onShutdown(() => {
73633
74291
  shutdown_requested = true;
74292
+ gitignore_watch_seq++;
74293
+ workspace_indexing_seq++;
74294
+ gitignore_watch_registration?.dispose();
73634
74295
  return shutdown_handler();
73635
74296
  });
73636
74297
  connection.onExit(create_exit_handler());
@@ -73668,6 +74329,7 @@ var init_server_factory = __esm(() => {
73668
74329
  init_file_path_utils();
73669
74330
  init_dependency_graph();
73670
74331
  init_esm();
74332
+ init_gitignore_matcher();
73671
74333
  init_stata_install_paths();
73672
74334
  init_diagnostic_resources();
73673
74335
  init_v18();
@@ -73864,4 +74526,4 @@ export {
73864
74526
  is_cli_entry_point
73865
74527
  };
73866
74528
 
73867
- //# debugId=19E8989026935ECD64756E2164756E21
74529
+ //# debugId=47C20F7ACC43ED9664756E2164756E21