@jbearak/sight 0.14.6 → 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.6",
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)) {
@@ -31502,8 +32039,8 @@ function format_help_link(topic, display) {
31502
32039
  }
31503
32040
 
31504
32041
  // src/providers/completion.ts
31505
- import * as fs10 from "fs";
31506
- import * as path12 from "path";
32042
+ import * as fs11 from "fs";
32043
+ import * as path13 from "path";
31507
32044
  function coerce_macro_map(value) {
31508
32045
  if (value instanceof Map) {
31509
32046
  return value;
@@ -32269,15 +32806,15 @@ class CompletionProvider {
32269
32806
  const path_parts = clean_path.split("/");
32270
32807
  search_prefix = path_parts.pop() || "";
32271
32808
  const dir_path = path_parts.join("/");
32272
- base_dir = path12.resolve(workspace_root, dir_path);
32809
+ base_dir = path13.resolve(workspace_root, dir_path);
32273
32810
  } else {
32274
32811
  search_prefix = clean_path;
32275
32812
  }
32276
32813
  }
32277
- if (!fs10.existsSync(base_dir) || !fs10.statSync(base_dir).isDirectory()) {
32814
+ if (!fs11.existsSync(base_dir) || !fs11.statSync(base_dir).isDirectory()) {
32278
32815
  return completions;
32279
32816
  }
32280
- const entries = fs10.readdirSync(base_dir, { withFileTypes: true });
32817
+ const entries = fs11.readdirSync(base_dir, { withFileTypes: true });
32281
32818
  for (const entry of entries) {
32282
32819
  if (entry.name.startsWith(".")) {
32283
32820
  continue;
@@ -32285,7 +32822,7 @@ class CompletionProvider {
32285
32822
  if (search_prefix && !entry.name.toLowerCase().startsWith(search_prefix.toLowerCase())) {
32286
32823
  continue;
32287
32824
  }
32288
- 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);
32289
32826
  if (entry_kind === "directory") {
32290
32827
  completions.push({
32291
32828
  label: entry.name + "/",
@@ -32313,17 +32850,17 @@ class CompletionProvider {
32313
32850
  get_workspace_root(document_uri) {
32314
32851
  try {
32315
32852
  const file_path = document_uri.replace(/^file:\/\//, "");
32316
- let current_dir = path12.dirname(file_path);
32317
- while (current_dir !== path12.dirname(current_dir)) {
32853
+ let current_dir = path13.dirname(file_path);
32854
+ while (current_dir !== path13.dirname(current_dir)) {
32318
32855
  const markers = [".git", "sight.toml", ".sight.json", "package.json", ".vscode"];
32319
32856
  for (const marker of markers) {
32320
- if (fs10.existsSync(path12.join(current_dir, marker))) {
32857
+ if (fs11.existsSync(path13.join(current_dir, marker))) {
32321
32858
  return current_dir;
32322
32859
  }
32323
32860
  }
32324
- current_dir = path12.dirname(current_dir);
32861
+ current_dir = path13.dirname(current_dir);
32325
32862
  }
32326
- return path12.dirname(file_path);
32863
+ return path13.dirname(file_path);
32327
32864
  } catch {
32328
32865
  return null;
32329
32866
  }
@@ -33581,7 +34118,7 @@ var init_help_resolver = __esm(() => {
33581
34118
  });
33582
34119
 
33583
34120
  // src/server-handlers.ts
33584
- import * as fs11 from "fs";
34121
+ import * as fs12 from "fs";
33585
34122
  function create_initialize_handler(on_capabilities_detected, on_initialization_options_detected, on_root_uri_detected) {
33586
34123
  return (params) => {
33587
34124
  const capabilities = params.capabilities;
@@ -33808,7 +34345,7 @@ function create_shutdown_handler(deps, disposables) {
33808
34345
  const SHUTDOWN_TIMEOUT_MS = 500;
33809
34346
  await Promise.race([
33810
34347
  deps.document_store.dispose(),
33811
- new Promise((resolve11) => setTimeout(resolve11, SHUTDOWN_TIMEOUT_MS))
34348
+ new Promise((resolve12) => setTimeout(resolve12, SHUTDOWN_TIMEOUT_MS))
33812
34349
  ]);
33813
34350
  }
33814
34351
  deps?.scope_resolver?.dispose();
@@ -33825,10 +34362,14 @@ function create_exit_handler(on_exit) {
33825
34362
  }
33826
34363
  };
33827
34364
  }
33828
- 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) {
33829
34366
  return (params) => {
33830
34367
  for (const my_event of params.changes) {
33831
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
+ }
33832
34373
  if (is_project_config_event_path(file_path)) {
33833
34374
  on_project_config_changed?.(my_event.uri);
33834
34375
  continue;
@@ -33911,7 +34452,7 @@ function create_shared_ihlp_resolver(deps, max_size = MAX_IHLP_CACHE_SIZE) {
33911
34452
  const my_cached = the_cache.get(my_path);
33912
34453
  if (my_cached !== undefined) {
33913
34454
  try {
33914
- const my_stat = await fs11.promises.stat(my_path);
34455
+ const my_stat = await fs12.promises.stat(my_path);
33915
34456
  if (my_stat.mtimeMs === my_cached.mtime_ms) {
33916
34457
  the_cache.delete(my_path);
33917
34458
  the_cache.set(my_path, my_cached);
@@ -33924,8 +34465,8 @@ function create_shared_ihlp_resolver(deps, max_size = MAX_IHLP_CACHE_SIZE) {
33924
34465
  }
33925
34466
  }
33926
34467
  try {
33927
- const my_stat = await fs11.promises.stat(my_path);
33928
- 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");
33929
34470
  if (the_cache.size >= max_size) {
33930
34471
  const my_first = the_cache.keys().next().value;
33931
34472
  if (my_first !== undefined) {
@@ -33962,7 +34503,7 @@ function create_resolve_sthlp_file_handler(deps, shared_ihlp) {
33962
34503
  if (!deps.workspace_indexer)
33963
34504
  return null;
33964
34505
  try {
33965
- const my_content = await fs11.promises.readFile(file_path, "utf-8");
34506
+ const my_content = await fs12.promises.readFile(file_path, "utf-8");
33966
34507
  return await expand_includes(my_content, my_ihlp_resolver);
33967
34508
  } catch {
33968
34509
  return null;
@@ -34041,7 +34582,7 @@ function create_expand_includes_handler(deps, shared_ihlp) {
34041
34582
  return { content: my_result };
34042
34583
  };
34043
34584
  }
34044
- 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;
34045
34586
  var init_server_handlers = __esm(() => {
34046
34587
  init_completion();
34047
34588
  init_context_tracker();
@@ -34090,6 +34631,9 @@ var init_server_handlers = __esm(() => {
34090
34631
  adoPaths: [],
34091
34632
  indexWorkspace: true,
34092
34633
  exclude: [],
34634
+ workspace: {
34635
+ respectGitignore: true
34636
+ },
34093
34637
  cross_file: {
34094
34638
  index_workspace: true,
34095
34639
  max_indexed_files: 1000,
@@ -34110,6 +34654,7 @@ var init_server_handlers = __esm(() => {
34110
34654
  },
34111
34655
  debug: false
34112
34656
  };
34657
+ GITIGNORE_PATH = /(?:^|[/\\])\.gitignore$/;
34113
34658
  });
34114
34659
 
34115
34660
  // src/utils/config-validator.ts
@@ -34251,6 +34796,13 @@ function validate_comment_formatting_config(config, log_warning) {
34251
34796
  if (typeof config.indexWorkspace === "boolean") {
34252
34797
  validated_config.indexWorkspace = config.indexWorkspace;
34253
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
+ }
34254
34806
  if (typeof config.debug === "boolean") {
34255
34807
  validated_config.debug = config.debug;
34256
34808
  }
@@ -34562,46 +35114,50 @@ var init_shared = __esm(() => {
34562
35114
  });
34563
35115
 
34564
35116
  // src/cli/source-files.ts
34565
- import * as fs12 from "fs";
34566
- import * as path13 from "path";
35117
+ import * as fs13 from "fs";
35118
+ import * as path14 from "path";
34567
35119
  import { TextDecoder } from "util";
34568
35120
  function canonicalize_existing_path(file_path) {
34569
- return fs12.realpathSync.native(file_path);
35121
+ return fs13.realpathSync.native(file_path);
34570
35122
  }
34571
35123
  function workspace_relative(workspace_root, file_path) {
34572
- const relative6 = path13.relative(workspace_root, file_path);
34573
- const inside = relative6 !== ".." && !relative6.startsWith(`..${path13.sep}`) && !path13.isAbsolute(relative6);
34574
- 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 };
34575
35127
  }
34576
35128
  function relative_path(workspace_root, file_path) {
34577
- const { relative: relative6 } = workspace_relative(workspace_root, file_path);
34578
- if (relative6 === "") {
35129
+ const { relative: relative7 } = workspace_relative(workspace_root, file_path);
35130
+ if (relative7 === "") {
34579
35131
  return ".";
34580
35132
  }
34581
- return path13.isAbsolute(relative6) ? file_path : relative6.split(path13.sep).join("/");
35133
+ return path14.isAbsolute(relative7) ? file_path : relative7.split(path14.sep).join("/");
34582
35134
  }
34583
35135
  function is_within_workspace(workspace_root, file_path) {
34584
- const { relative: relative6, inside } = workspace_relative(workspace_root, file_path);
34585
- return relative6 === "" || relative6.length > 0 && inside;
35136
+ const { relative: relative7, inside } = workspace_relative(workspace_root, file_path);
35137
+ return relative7 === "" || relative7.length > 0 && inside;
34586
35138
  }
34587
- 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;
34588
35142
  let entries;
34589
35143
  try {
34590
- entries = fs12.readdirSync(dir_path, { withFileTypes: true });
35144
+ entries = fs13.readdirSync(dir_path, { withFileTypes: true });
34591
35145
  } catch (error) {
34592
35146
  operator_errors.push(`cannot read directory: ${dir_path}: ${error_message(error)}`);
34593
35147
  return;
34594
35148
  }
34595
35149
  for (const entry of entries) {
34596
- const entry_path = path13.join(dir_path, entry.name);
35150
+ const entry_path = path14.join(dir_path, entry.name);
34597
35151
  if (entry.isDirectory()) {
34598
35152
  if (entry.name.startsWith("."))
34599
35153
  continue;
34600
35154
  if (!exclude_matcher.is_empty && exclude_matcher.is_excluded_dir(entry_path, workspace_roots)) {
34601
35155
  continue;
34602
35156
  }
34603
- 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);
34604
35158
  } else if (entry.isFile() && hasStataExtension(entry.name)) {
35159
+ if (gitignore_matcher.is_ignored(entry_path, "file"))
35160
+ continue;
34605
35161
  if (!exclude_matcher.is_empty && exclude_matcher.is_excluded_file(entry_path, workspace_roots)) {
34606
35162
  continue;
34607
35163
  }
@@ -34609,20 +35165,21 @@ function walk_sources(dir_path, out, operator_errors, workspace_roots, exclude_m
34609
35165
  }
34610
35166
  }
34611
35167
  }
34612
- 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) {
34613
35169
  const operator_errors = [];
34614
35170
  const source_paths = [];
34615
- let normalized_root = path13.resolve(workspace_root);
35171
+ let normalized_root = path14.resolve(workspace_root);
34616
35172
  try {
34617
35173
  normalized_root = canonicalize_existing_path(normalized_root);
34618
35174
  } catch {}
34619
35175
  const exclude_matcher = create_exclude_matcher(exclude_patterns);
34620
35176
  const exclude_roots = [normalized_root];
35177
+ const gitignore_matcher = create_gitignore_matcher(exclude_roots, respect_gitignore);
34621
35178
  const has_explicit_paths = input_paths.length > 0;
34622
35179
  const paths_to_collect = input_paths.length > 0 ? input_paths : [normalized_root];
34623
35180
  for (const input_path of paths_to_collect) {
34624
- const resolved_path = path13.resolve(cwd, input_path);
34625
- if (!fs12.existsSync(resolved_path)) {
35181
+ const resolved_path = path14.resolve(cwd, input_path);
35182
+ if (!fs13.existsSync(resolved_path)) {
34626
35183
  operator_errors.push(`path does not exist: ${input_path}`);
34627
35184
  continue;
34628
35185
  }
@@ -34635,13 +35192,13 @@ function collect_report_targets(input_paths, workspace_root, cwd, exclude_patter
34635
35192
  }
34636
35193
  let stat;
34637
35194
  try {
34638
- stat = fs12.statSync(absolute_path);
35195
+ stat = fs13.statSync(absolute_path);
34639
35196
  } catch (error) {
34640
35197
  operator_errors.push(`cannot stat path: ${input_path}: ${error_message(error)}`);
34641
35198
  continue;
34642
35199
  }
34643
35200
  if (stat.isDirectory()) {
34644
- 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);
34645
35202
  } else if (stat.isFile() && hasStataExtension(absolute_path)) {
34646
35203
  source_paths.push(absolute_path);
34647
35204
  }
@@ -34730,7 +35287,7 @@ function decode_error_diagnostic(offset) {
34730
35287
  function read_source_file(file_path) {
34731
35288
  let bytes;
34732
35289
  try {
34733
- bytes = fs12.readFileSync(file_path);
35290
+ bytes = fs13.readFileSync(file_path);
34734
35291
  } catch (error) {
34735
35292
  return {
34736
35293
  kind: "read-error",
@@ -34754,6 +35311,7 @@ var init_source_files = __esm(() => {
34754
35311
  init_file_path_utils();
34755
35312
  init_exclude_matcher();
34756
35313
  init_diagnostic_code_description();
35314
+ init_gitignore_matcher();
34757
35315
  init_shared();
34758
35316
  import_vscode_languageserver6 = __toESM(require_main4(), 1);
34759
35317
  });
@@ -34768,8 +35326,8 @@ __export(exports_check, {
34768
35326
  collect_check_diagnostics: () => collect_check_diagnostics,
34769
35327
  build_check_context: () => build_check_context
34770
35328
  });
34771
- import * as fs13 from "fs";
34772
- import * as path14 from "path";
35329
+ import * as fs14 from "fs";
35330
+ import * as path15 from "path";
34773
35331
  function parse_required_option_value(argv, index, flag, value_kind, inline_value) {
34774
35332
  if (inline_value !== undefined) {
34775
35333
  if (inline_value.length === 0) {
@@ -34935,7 +35493,7 @@ function load_check_config(options) {
34935
35493
  warnings: validation_warnings
34936
35494
  };
34937
35495
  }
34938
- 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);
34939
35497
  if (loaded.kind === "load-failed") {
34940
35498
  return {
34941
35499
  kind: "operator-error",
@@ -35031,7 +35589,7 @@ async function collect_check_diagnostics(context, workspace_root, config, target
35031
35589
  const uri = URI.file(target.path).toString();
35032
35590
  let stats;
35033
35591
  try {
35034
- stats = fs13.statSync(target.path);
35592
+ stats = fs14.statSync(target.path);
35035
35593
  } catch (error) {
35036
35594
  records.push(diagnostic_record(target.relative_path, unreadable_diagnostic(read_error_detail(error))));
35037
35595
  return records;
@@ -35042,7 +35600,7 @@ async function collect_check_diagnostics(context, workspace_root, config, target
35042
35600
  }
35043
35601
  return records;
35044
35602
  }
35045
- 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])) {
35046
35604
  records.push(diagnostic_record(target.relative_path, index_limit_diagnostic()));
35047
35605
  return records;
35048
35606
  }
@@ -35126,10 +35684,10 @@ async function run_check_with_cwd(argv, cwd, output = DEFAULT_OUTPUT) {
35126
35684
  `);
35127
35685
  return EXIT_OK;
35128
35686
  }
35129
- const resolved_workspace_root = path14.resolve(cwd, result.args.workspace ?? ".");
35687
+ const resolved_workspace_root = path15.resolve(cwd, result.args.workspace ?? ".");
35130
35688
  let is_workspace_directory = false;
35131
35689
  try {
35132
- is_workspace_directory = fs13.statSync(resolved_workspace_root).isDirectory();
35690
+ is_workspace_directory = fs14.statSync(resolved_workspace_root).isDirectory();
35133
35691
  } catch {
35134
35692
  is_workspace_directory = false;
35135
35693
  }
@@ -35161,7 +35719,7 @@ async function run_check_with_cwd(argv, cwd, output = DEFAULT_OUTPUT) {
35161
35719
  `);
35162
35720
  return EXIT_OPERATOR_ERROR;
35163
35721
  }
35164
- 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);
35165
35723
  if (target_result.operator_errors.length > 0) {
35166
35724
  for (const message of target_result.operator_errors) {
35167
35725
  output.stderr(`sight check: ${message}
@@ -35490,7 +36048,7 @@ function is_position_in_range3(position, range) {
35490
36048
  }
35491
36049
 
35492
36050
  // src/providers/hover.ts
35493
- import * as path15 from "path";
36051
+ import * as path16 from "path";
35494
36052
  function has_definition_index(hit) {
35495
36053
  return typeof hit.definition_index === "number";
35496
36054
  }
@@ -36840,7 +37398,7 @@ ${source_info}${footer}`
36840
37398
  if (this.looks_like_uri_scheme(uri_or_path)) {
36841
37399
  return null;
36842
37400
  }
36843
- return path15.resolve(uri_or_path);
37401
+ return path16.resolve(uri_or_path);
36844
37402
  }
36845
37403
  escape_markdown_link_text(text) {
36846
37404
  return text.replace(/[\\[\]()]/g, "\\$&");
@@ -36860,11 +37418,11 @@ ${source_info}${footer}`
36860
37418
  if (workspace_fs_path === null) {
36861
37419
  return fs_path;
36862
37420
  }
36863
- const relative7 = path15.relative(workspace_fs_path, fs_path);
36864
- if (relative7.startsWith("..") || path15.isAbsolute(relative7)) {
37421
+ const relative8 = path16.relative(workspace_fs_path, fs_path);
37422
+ if (relative8.startsWith("..") || path16.isAbsolute(relative8)) {
36865
37423
  return fs_path;
36866
37424
  }
36867
- return relative7;
37425
+ return relative8;
36868
37426
  }
36869
37427
  format_source_link(source_uri, current_uri, workspace_root) {
36870
37428
  const source_path = this.normalize_file_path(source_uri);
@@ -37215,7 +37773,7 @@ var init_hover = __esm(() => {
37215
37773
  });
37216
37774
 
37217
37775
  // src/providers/definition.ts
37218
- import * as path16 from "path";
37776
+ import * as path17 from "path";
37219
37777
 
37220
37778
  class DefinitionProvider {
37221
37779
  workspace_roots = [];
@@ -37960,7 +38518,7 @@ class DefinitionProvider {
37960
38518
  if (!the_call) {
37961
38519
  return { matched: false, path: null };
37962
38520
  }
37963
- const current_dir = path16.dirname(URI.parse(document.uri).fsPath);
38521
+ const current_dir = path17.dirname(URI.parse(document.uri).fsPath);
37964
38522
  const my_outcome = resolve_forward_call_rich(file_path, current_dir, the_call.working_directory, { workspace_roots: this.workspace_roots });
37965
38523
  if (my_outcome.kind === "exact" || my_outcome.kind === "case_only") {
37966
38524
  return { matched: true, path: my_outcome.path };
@@ -37969,8 +38527,8 @@ class DefinitionProvider {
37969
38527
  }
37970
38528
  resolve_file_path(current_uri, file_path) {
37971
38529
  const current_path = URI.parse(current_uri).fsPath;
37972
- const current_dir = path16.dirname(current_path);
37973
- 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);
37974
38532
  const the_roots_set = new Set(this.workspace_roots);
37975
38533
  the_roots_set.add(current_dir);
37976
38534
  const the_roots = Array.from(the_roots_set);
@@ -38544,7 +39102,7 @@ class ReferencesProvider {
38544
39102
  }
38545
39103
  file_count++;
38546
39104
  if (file_count % 10 === 0) {
38547
- await new Promise((resolve15) => setTimeout(resolve15, 0));
39105
+ await new Promise((resolve16) => setTimeout(resolve16, 0));
38548
39106
  if (cancellation_token?.isCancellationRequested) {
38549
39107
  break;
38550
39108
  }
@@ -38970,7 +39528,7 @@ var init_section_detector = __esm(() => {
38970
39528
  });
38971
39529
 
38972
39530
  // src/providers/symbols.ts
38973
- import * as path17 from "path";
39531
+ import * as path18 from "path";
38974
39532
  function is_position_in_range4(position, range) {
38975
39533
  if (position.line < range.start.line) {
38976
39534
  return false;
@@ -39366,7 +39924,7 @@ class SymbolProvider {
39366
39924
  }
39367
39925
  }
39368
39926
  for (const document of all_documents) {
39369
- const my_basename = path17.basename(document.uri);
39927
+ const my_basename = path18.basename(document.uri);
39370
39928
  for (const my_program of document.symbols.programs.values()) {
39371
39929
  if (my_program.name.toLowerCase().includes(lower_query)) {
39372
39930
  symbols.push({
@@ -39623,6 +40181,13 @@ class IndentationAnalyzer {
39623
40181
  this.process_embedded_block_node(node);
39624
40182
  return;
39625
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
+ }
39626
40191
  if (this.is_block_node(node)) {
39627
40192
  if (node.type === "command") {
39628
40193
  const cmd = node;
@@ -41297,6 +41862,12 @@ class PrettyPrinter {
41297
41862
  return spaced.replace(/\(\s+/g, "(").replace(/\s+\)/g, ")");
41298
41863
  }
41299
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
+ }
41300
41871
  const the_lines = [];
41301
41872
  let header = this.getIndent();
41302
41873
  switch (node.type) {
@@ -41339,7 +41910,7 @@ class PrettyPrinter {
41339
41910
  }
41340
41911
  printEmbeddedBlock(node) {
41341
41912
  if (node.is_single_line) {
41342
- return `${this.getIndent()}${node.start_command} ${node.content}${this.getStatementTerminator()}`;
41913
+ return `${this.getIndent()}${node.start_command} ${node.content}`;
41343
41914
  }
41344
41915
  const the_lines = [];
41345
41916
  the_lines.push(`${this.getIndent()}${node.start_command}`);
@@ -41811,8 +42382,8 @@ class DocumentDebounceManager {
41811
42382
  if (prev_resolver) {
41812
42383
  prev_resolver();
41813
42384
  }
41814
- const promise = new Promise((resolve15) => {
41815
- this.pending_resolvers.set(uri, resolve15);
42385
+ const promise = new Promise((resolve16) => {
42386
+ this.pending_resolvers.set(uri, resolve16);
41816
42387
  });
41817
42388
  this.pending_promises.set(uri, promise);
41818
42389
  const timer = setTimeout(() => {
@@ -41838,9 +42409,9 @@ class DocumentDebounceManager {
41838
42409
  if (this.parse_queue.length >= this.MAX_QUEUE_LENGTH) {
41839
42410
  logger.warn(`Parse queue full, dropping ${uri} v${version}`);
41840
42411
  this.metrics.dropped_parses++;
41841
- const resolve15 = this.pending_resolvers.get(uri);
41842
- if (resolve15) {
41843
- resolve15();
42412
+ const resolve16 = this.pending_resolvers.get(uri);
42413
+ if (resolve16) {
42414
+ resolve16();
41844
42415
  this.pending_resolvers.delete(uri);
41845
42416
  this.pending_promises.delete(uri);
41846
42417
  }
@@ -41863,7 +42434,7 @@ class DocumentDebounceManager {
41863
42434
  }
41864
42435
  this.active_parses++;
41865
42436
  try {
41866
- await new Promise((resolve15) => setImmediate(resolve15));
42437
+ await new Promise((resolve16) => setImmediate(resolve16));
41867
42438
  await callback();
41868
42439
  } catch (error) {
41869
42440
  logger.error(`Parse error for ${uri}: ${error}`);
@@ -41895,9 +42466,9 @@ class DocumentDebounceManager {
41895
42466
  clearTimeout(existing);
41896
42467
  this.pending_timers.delete(uri);
41897
42468
  }
41898
- const resolve15 = this.pending_resolvers.get(uri);
41899
- if (resolve15) {
41900
- resolve15();
42469
+ const resolve16 = this.pending_resolvers.get(uri);
42470
+ if (resolve16) {
42471
+ resolve16();
41901
42472
  this.pending_resolvers.delete(uri);
41902
42473
  this.pending_promises.delete(uri);
41903
42474
  }
@@ -72719,7 +73290,8 @@ __export(exports_server_factory, {
72719
73290
  create_server: () => create_server,
72720
73291
  build_non_capability_settings_from_sources: () => build_non_capability_settings_from_sources
72721
73292
  });
72722
- import * as fs14 from "fs";
73293
+ import * as fs15 from "fs";
73294
+ import * as path19 from "path";
72723
73295
  function create_transport_connection(transport) {
72724
73296
  if (transport === "stdio") {
72725
73297
  return import_node8.createConnection(process.stdin, process.stdout);
@@ -72755,6 +73327,7 @@ function indexing_affecting_signature(config) {
72755
73327
  return JSON.stringify({
72756
73328
  adoPaths: config?.adoPaths ?? null,
72757
73329
  exclude: config?.exclude ?? null,
73330
+ respectGitignore: config?.workspace?.respectGitignore ?? true,
72758
73331
  indexWorkspace: config?.indexWorkspace ?? null,
72759
73332
  index_workspace: config?.cross_file?.index_workspace ?? null,
72760
73333
  max_indexed_files: config?.cross_file?.max_indexed_files ?? null,
@@ -72797,6 +73370,13 @@ async function create_server(options) {
72797
73370
  let project_config_candidate_dirs = [];
72798
73371
  let active_workspace_roots = [];
72799
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;
72800
73380
  let last_applied_indexing_signature = "";
72801
73381
  let config_change_seq = 0;
72802
73382
  let init_options_config = undefined;
@@ -72898,6 +73478,65 @@ async function create_server(options) {
72898
73478
  }
72899
73479
  previous_registration?.dispose();
72900
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
+ }
72901
73540
  function build_non_capability_settings() {
72902
73541
  return build_non_capability_settings_from_sources({
72903
73542
  init_options_config,
@@ -73106,10 +73745,16 @@ async function create_server(options) {
73106
73745
  scope_resolver?.reset_reverse_deps();
73107
73746
  }
73108
73747
  function configure_workspace_indexing(settings, folder_paths, reset_indexes) {
73748
+ const my_indexing_seq = ++workspace_indexing_seq;
73749
+ gitignore_refresh_pending = false;
73109
73750
  if (reset_indexes) {
73110
73751
  reset_workspace_indexing_state();
73111
73752
  }
73112
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
+ });
73113
73758
  configure_completion_provider(settings);
73114
73759
  apply_cache_capacities(settings);
73115
73760
  if (workspace_indexer) {
@@ -73117,8 +73762,13 @@ async function create_server(options) {
73117
73762
  workspace_indexer.set_max_indexed_files(settings.cross_file?.max_indexed_files ?? 1000);
73118
73763
  }
73119
73764
  const indexing_enabled = settings.indexWorkspace !== false && settings.cross_file?.index_workspace !== false;
73120
- 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
+ }
73121
73769
  workspace_indexer.initialize(folder_paths, settings.adoPaths || []).then(() => {
73770
+ if (my_indexing_seq !== workspace_indexing_seq || shutdown_requested)
73771
+ return;
73122
73772
  resolve_sthlp_handler?.clear_negative_cache();
73123
73773
  if (dependency_graph?.is_scan_complete()) {
73124
73774
  revalidate_all_open_docs();
@@ -73160,7 +73810,7 @@ async function create_server(options) {
73160
73810
  global_settings = build_non_capability_settings();
73161
73811
  }
73162
73812
  const settings = await get_document_settings("");
73163
- 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;
73164
73814
  if (indexing_changed) {
73165
73815
  configure_workspace_indexing(settings, active_workspace_roots, true);
73166
73816
  } else {
@@ -73415,14 +74065,14 @@ ${scope_resolver.get_reverse_deps_debug_info()}`);
73415
74065
  return open_doc.getText();
73416
74066
  }
73417
74067
  const fs_path = URI.parse(uri).fsPath;
73418
- return fs14.promises.readFile(fs_path, "utf8");
74068
+ return fs15.promises.readFile(fs_path, "utf8");
73419
74069
  },
73420
74070
  exists: async (uri) => {
73421
74071
  if (documents.get(uri))
73422
74072
  return true;
73423
74073
  const fs_path = URI.parse(uri).fsPath;
73424
74074
  try {
73425
- await fs14.promises.access(fs_path);
74075
+ await fs15.promises.access(fs_path);
73426
74076
  return true;
73427
74077
  } catch {
73428
74078
  return false;
@@ -73504,7 +74154,7 @@ ${scope_resolver.get_reverse_deps_debug_info()}`);
73504
74154
  }));
73505
74155
  function apply_runtime_settings_change(settings) {
73506
74156
  const new_signature = indexing_affecting_signature(settings);
73507
- if (new_signature !== last_applied_indexing_signature) {
74157
+ if (gitignore_refresh_pending || new_signature !== last_applied_indexing_signature) {
73508
74158
  configure_workspace_indexing(settings, active_workspace_roots, true);
73509
74159
  } else {
73510
74160
  configure_completion_provider(settings);
@@ -73580,6 +74230,9 @@ ${scope_resolver.get_reverse_deps_debug_info()}`);
73580
74230
  }
73581
74231
  if (dependency_graph) {
73582
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
+ }
73583
74236
  if (affected_callees.size > 0) {
73584
74237
  invalidate_and_revalidate_callees(affected_callees);
73585
74238
  }
@@ -73601,7 +74254,7 @@ ${scope_resolver.get_reverse_deps_debug_info()}`);
73601
74254
  }
73602
74255
  }, async () => {
73603
74256
  await reload_project_config_from_active_root();
73604
- }));
74257
+ }, on_gitignore_changed));
73605
74258
  connection.onNotification(DIAGNOSTIC_RESOURCES_CHANGED_NOTIFICATION, (params) => {
73606
74259
  const next = diagnostic_uris_from_notification(params);
73607
74260
  if (next !== undefined) {
@@ -73636,6 +74289,9 @@ ${scope_resolver.get_reverse_deps_debug_info()}`);
73636
74289
  });
73637
74290
  connection.onShutdown(() => {
73638
74291
  shutdown_requested = true;
74292
+ gitignore_watch_seq++;
74293
+ workspace_indexing_seq++;
74294
+ gitignore_watch_registration?.dispose();
73639
74295
  return shutdown_handler();
73640
74296
  });
73641
74297
  connection.onExit(create_exit_handler());
@@ -73673,6 +74329,7 @@ var init_server_factory = __esm(() => {
73673
74329
  init_file_path_utils();
73674
74330
  init_dependency_graph();
73675
74331
  init_esm();
74332
+ init_gitignore_matcher();
73676
74333
  init_stata_install_paths();
73677
74334
  init_diagnostic_resources();
73678
74335
  init_v18();
@@ -73869,4 +74526,4 @@ export {
73869
74526
  is_cli_entry_point
73870
74527
  };
73871
74528
 
73872
- //# debugId=A1706D274D80E2DC64756E2164756E21
74529
+ //# debugId=47C20F7ACC43ED9664756E2164756E21