@mrclrchtr/supi-lsp 8.0.0 → 9.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,19 +1,17 @@
1
1
  "use strict";
2
2
 
3
- var _TRAILING_WILD_CARD_R;
4
3
  function _typeof(obj) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (obj) { return typeof obj; } : function (obj) { return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }, _typeof(obj); }
5
4
  function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
6
5
  function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, _toPropertyKey(descriptor.key), descriptor); } }
7
6
  function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; }
7
+ function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return _typeof(key) === "symbol" ? key : String(key); }
8
+ function _toPrimitive(input, hint) { if (_typeof(input) !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (_typeof(res) !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); }
8
9
  function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); }
9
10
  function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
10
11
  function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
11
12
  function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; }
12
13
  function _iterableToArrayLimit(arr, i) { var _i = null == arr ? null : "undefined" != typeof Symbol && arr[Symbol.iterator] || arr["@@iterator"]; if (null != _i) { var _s, _e, _x, _r, _arr = [], _n = !0, _d = !1; try { if (_x = (_i = _i.call(arr)).next, 0 === i) { if (Object(_i) !== _i) return; _n = !1; } else for (; !(_n = (_s = _x.call(_i)).done) && (_arr.push(_s.value), _arr.length !== i); _n = !0); } catch (err) { _d = !0, _e = err; } finally { try { if (!_n && null != _i["return"] && (_r = _i["return"](), Object(_r) !== _r)) return; } finally { if (_d) throw _e; } } return _arr; } }
13
14
  function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
14
- function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
15
- function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return _typeof(key) === "symbol" ? key : String(key); }
16
- function _toPrimitive(input, hint) { if (_typeof(input) !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (_typeof(res) !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); }
17
15
  // A simple implementation of make-array
18
16
  function makeArray(subject) {
19
17
  return Array.isArray(subject) ? subject : [subject];
@@ -26,12 +24,7 @@ var ESCAPE = '\\';
26
24
  // The characters that carry a meaning of their own inside a regular
27
25
  // expression, so a literal one has to be escaped before it is emitted.
28
26
  var REGEX_LITERAL_SPECIAL = /[.*+?()[\]{}^$|\\/]/;
29
- // A line of only spaces is blank -- the trailing-space trimming empties it --
30
- // but a line holding a tab is a pattern for a tab-named path, since git
31
- // never trims a tab.
32
- // A leading BOM is removed during compilation, so reject a line that would
33
- // become empty after removing it and trimming spaces.
34
- var REGEX_TEST_BLANK_LINE = /^\uFEFF? *$/;
27
+ var BOM = "\uFEFF";
35
28
  var REGEX_INVALID_TRAILING_BACKSLASH = /(?:[^\\]|^)\\$/;
36
29
  var REGEX_REPLACE_LEADING_EXCAPED_EXCLAMATION = /^\\!/;
37
30
  var REGEX_REPLACE_LEADING_EXCAPED_HASH = /^\\#/;
@@ -245,6 +238,11 @@ var REGEX_RESTORE_PLACEHOLDER = new RegExp("".concat(PLACEHOLDER, "(\\d+)").conc
245
238
  // into a `RegExp` -- `_make` always turns it back into a real wildcard first.
246
239
  var TRAILING_WILDCARD = "\uE000";
247
240
 
241
+ // A trailing "/**" is deferred the same way, because `checkRegex` has to tell
242
+ // it apart from a trailing "/*" (see `checkSourceOf`). For `.ignores()` it
243
+ // still never matches the folder itself (#21).
244
+ var TRAILING_DOUBLESTAR = "\uE001";
245
+
248
246
  // Replace every bracket expression with a placeholder the replacers below
249
247
  // leave alone, and translate it separately.
250
248
  var extractBrackets = function extractBrackets(pattern) {
@@ -272,10 +270,13 @@ var extractBrackets = function extractBrackets(pattern) {
272
270
  // wildcard by `TRAILING_WILDCARD` and the wildcard replacers), `\[`
273
271
  // (a literal bracket, the one `[` the bracket replacer still expects),
274
272
  // `\ ` (a quoted trailing space), and `\\` (a literal backslash). A
275
- // lone trailing backslash never reaches here -- `checkPattern` throws
276
- // it out first.
273
+ // lone trailing backslash can reach here after line-ending cleanup.
277
274
  var escaped = pattern[index + 1];
278
- if (escaped === '*' || escaped === '[' || escaped === SPACE || escaped === ESCAPE) {
275
+ if (escaped === UNDEFINED || escaped === SLASH && index + 2 === length) {
276
+ // Git removes a final directory slash before matching. An escape
277
+ // without a character after that removal makes the pattern invalid.
278
+ out += hold(NEVER_MATCH);
279
+ } else if (escaped === '*' || escaped === '[' || escaped === SPACE || escaped === ESCAPE) {
279
280
  out += pattern.slice(index, index + 2);
280
281
  } else {
281
282
  out += hold(REGEX_LITERAL_SPECIAL.test(escaped) ? ESCAPE + escaped : escaped);
@@ -349,33 +350,7 @@ var REGEX_INNER_SLASH = /\/(?!$)/;
349
350
  // that then finds nothing -- for the wildcard step, whose `[^\\]+`
350
351
  // backtracks its way through the whole string before giving up, 11ns
351
352
  // against 400ns.
352
- var REPLACERS = [[
353
- // Remove BOM
354
- // TODO:
355
- // Other similar zero-width characters?
356
- /^\uFEFF/, function () {
357
- return EMPTY;
358
- }, "\uFEFF"], [
359
- // A trailing line terminator, left on when a whole file's contents are
360
- // added as one pattern rather than split into lines. git never sees one
361
- // -- it reads a `.gitignore` line by line -- so it is not part of the
362
- // pattern and is dropped here, apart from the trailing-space trimming,
363
- // which follows git in touching spaces and nothing else.
364
- /[\r\n]+$/, function () {
365
- return EMPTY;
366
- }],
367
- // > Trailing spaces are ignored unless they are quoted with backslash ("\")
368
- [
369
- // Only spaces, never tabs or other whitespace: git trims a trailing run
370
- // of `' '` and nothing else (dir.c, `trim_trailing_spaces`, a single
371
- // `case ' '`), so a pattern ending in a tab keeps it as a literal.
372
- // (a\ ) -> (a )
373
- // (a ) -> (a)
374
- // (a ) -> (a)
375
- // (a \ ) -> (a )
376
- /((?:\\\\)*?)(\\? +)$/, function (_, m1, m2) {
377
- return m1 + (m2.indexOf('\\') === 0 ? SPACE : EMPTY);
378
- }],
353
+ var REPLACERS = [
379
354
  // Replace (\ ) with ' '
380
355
  // Only a space: an escaped tab or other whitespace is already a literal by
381
356
  // the time it reaches here, and a bare tab must be left as one, not turned
@@ -383,10 +358,13 @@ var REPLACERS = [[
383
358
  // (\ ) -> ' '
384
359
  // (\\ ) -> '\\ '
385
360
  // (\\\ ) -> '\\ '
386
- [/(\\+?) /g, function (_, m1) {
387
- var length = m1.length;
388
- return m1.slice(0, length - length % 2) + SPACE;
389
- }],
361
+ [
362
+ // A run of backslashes is taken whole, from its first one, so no match
363
+ // ever starts again inside it -- `(\\+?) ` did, which made a long run
364
+ // quadratic.
365
+ /(\\+)( ?)/g, function (_, run, space) {
366
+ return space ? run.slice(0, run.length - run.length % 2) + SPACE : run;
367
+ }, ESCAPE + SPACE],
390
368
  // Escape metacharacters
391
369
  // which is written down by users but means special for regular expressions.
392
370
 
@@ -494,8 +472,9 @@ function (_, index, str) {
494
472
  // case: /**
495
473
  // > A trailing `"/**"` matches everything inside.
496
474
 
497
- // #21: everything inside but it should not include the current folder
498
- : '\\/.+';
475
+ // #21: everything inside but it should not include the current folder,
476
+ // resolved by `_make`
477
+ : "\\/".concat(TRAILING_DOUBLESTAR);
499
478
  }, '*'],
500
479
  // normal intermediate wildcards
501
480
  [
@@ -580,10 +559,11 @@ DIRECT,
580
559
  function (source) {
581
560
  var last = source[source.length - 1];
582
561
 
583
- // The pattern is empty, or ends in the pending trailing wildcard the next
584
- // step owns. A trailing `*` that is not the marker is a literal star,
585
- // which anchors like any other final character.
586
- if (!last || last === TRAILING_WILDCARD) {
562
+ // The pattern is empty, or ends in a pending marker `_make` owns --
563
+ // the trailing wildcard, or a trailing "/**". A trailing `*` that is
564
+ // not the marker is a literal star, which anchors like any other
565
+ // final character.
566
+ if (!last || last === TRAILING_WILDCARD || last === TRAILING_DOUBLESTAR) {
587
567
  return source;
588
568
  }
589
569
  return last === SLASH
@@ -595,7 +575,7 @@ var REGEX_REPLACE_TRAILING_WILDCARD = /(^|\\\/)?\uE000$/;
595
575
  var MODE_IGNORE = 'regex';
596
576
  var MODE_CHECK_IGNORE = 'checkRegex';
597
577
  var UNDERSCORE = '_';
598
- var TRAILING_WILD_CARD_REPLACERS = (_TRAILING_WILD_CARD_R = {}, _defineProperty(_TRAILING_WILD_CARD_R, MODE_IGNORE, function (_, p1) {
578
+ var replaceTrailingWildcard = function replaceTrailingWildcard(_, p1) {
599
579
  var prefix = p1
600
580
  // '\^':
601
581
  // '/*' does not match EMPTY
@@ -607,16 +587,13 @@ var TRAILING_WILD_CARD_REPLACERS = (_TRAILING_WILD_CARD_R = {}, _defineProperty(
607
587
  // 'a*' matches 'aa'
608
588
  : '[^/]*';
609
589
  return "".concat(prefix, "(?=$|\\/$)");
610
- }), _defineProperty(_TRAILING_WILD_CARD_R, MODE_CHECK_IGNORE, function (_, p1) {
611
- // When doing `git check-ignore`
612
- var prefix = p1
613
- // '\\\/':
614
- // 'abc/*' DOES match 'abc/' !
615
- ? "".concat(p1, "[^/]*") // 'a*' matches 'a'
616
- // 'a*' matches 'aa'
617
- : '[^/]*';
618
- return "".concat(prefix, "(?=$|\\/$)");
619
- }), _TRAILING_WILD_CARD_R);
590
+ };
591
+ var REGEX_REPLACE_TRAILING_DOUBLESTAR = /\uE001$/;
592
+
593
+ // 'abc/**' matches everything under 'abc', but not 'abc/' itself (#21)
594
+ var replaceTrailingDoublestar = function replaceTrailingDoublestar() {
595
+ return '.+(?=$|\\/$)';
596
+ };
620
597
  var WILDCARD = '[^\\/]*';
621
598
 
622
599
  // Where a run of non-slash wildcards is split by single fixed characters --
@@ -785,6 +762,22 @@ var makeRegexPrefix = function makeRegexPrefix(pattern) {
785
762
  }) : replaced;
786
763
  };
787
764
 
765
+ // `checkRegex` tests a path with a trailing slash, 'abc/', the way
766
+ // `git check-ignore` matches that literal string once the directory itself
767
+ // is known not to be excluded (see `checkIgnore`): a trailing '/' of the
768
+ // pattern is dropped, a basename pattern sees an empty basename, and only a
769
+ // pattern whose last segment is a pending wildcard can match what is left
770
+ // after the final slash -- 'abc/*' and 'abc/**' match 'abc/', and 'abc/**'
771
+ // also matches 'abc/d/' (#77, #169).
772
+ var checkSourceOf = function checkSourceOf(body, prefix) {
773
+ if (body[body.length - 1] === SLASH) {
774
+ prefix = makeRegexPrefix(body.slice(0, -1));
775
+ }
776
+ var head = prefix.slice(0, -1);
777
+ var last = prefix[prefix.length - 1];
778
+ return last === TRAILING_WILDCARD ? "".concat(head, "$") : last === TRAILING_DOUBLESTAR ? "".concat(head, ".*$") : NEVER_MATCH;
779
+ };
780
+
788
781
  // A trailing slash does not stop a pattern being basename-only: it restricts
789
782
  // the match to a directory, it does not let the pattern reach across one.
790
783
  // Everything else a pattern can hold -- a wildcard, a character class, an
@@ -840,12 +833,10 @@ var isString = function isString(subject) {
840
833
  return typeof subject === 'string';
841
834
  };
842
835
 
843
- // > A blank line matches no files, so it can serve as a separator for readability.
836
+ // Blank lines and comments are told by `createRule`, once the pattern is
837
+ // normalized.
844
838
  var checkPattern = function checkPattern(pattern) {
845
- return pattern && isString(pattern) && !REGEX_TEST_BLANK_LINE.test(pattern) && !REGEX_INVALID_TRAILING_BACKSLASH.test(pattern)
846
-
847
- // > A line starting with # serves as a comment.
848
- && pattern.indexOf('#') !== 0;
839
+ return pattern && isString(pattern) && !REGEX_INVALID_TRAILING_BACKSLASH.test(pattern);
849
840
  };
850
841
  var splitPattern = function splitPattern(pattern) {
851
842
  return pattern.split(REGEX_SPLITALL_CRLF).filter(Boolean);
@@ -892,25 +883,73 @@ var IgnoreRule = /*#__PURE__*/function () {
892
883
  }, {
893
884
  key: "_make",
894
885
  value: function _make(mode, key) {
895
- var str = pinWildcards(this.regexPrefix.replace(REGEX_REPLACE_TRAILING_WILDCARD,
896
- // It does not need to bind pattern
897
- TRAILING_WILD_CARD_REPLACERS[mode]));
886
+ var str = pinWildcards(mode === MODE_IGNORE ? this.regexPrefix.replace(REGEX_REPLACE_TRAILING_WILDCARD, replaceTrailingWildcard).replace(REGEX_REPLACE_TRAILING_DOUBLESTAR, replaceTrailingDoublestar) : checkSourceOf(this.body, this.regexPrefix));
898
887
  var regex = this.ignoreCase ? new RegExp(str, 'i') : new RegExp(str);
899
888
  return define(this, key, regex);
900
889
  }
901
890
  }]);
902
891
  return IgnoreRule;
903
892
  }();
893
+ var isLineEnd = function isLineEnd(_char5) {
894
+ return _char5 === '\r' || _char5 === '\n';
895
+ };
896
+
897
+ // Drop a line terminator, which can remain when patterns are passed as an
898
+ // array, and then the trailing spaces. Git trims spaces only, and a space
899
+ // escaped by an odd run of backslashes stays, unescaped, as the last one.
900
+ // Scanned from the end: a regular expression can only try each start in
901
+ // turn, which is quadratic over a long run of spaces or backslashes.
902
+ // 'a ' -> 'a'; 'a\ ' -> 'a '; 'a\\ ' -> 'a\\'; 'a\t' -> 'a\t'
903
+ var trimEnd = function trimEnd(body) {
904
+ var end = body.length;
905
+ while (end && isLineEnd(body[end - 1])) {
906
+ end--;
907
+ }
908
+ var lineEnd = end;
909
+ while (end && body[end - 1] === SPACE) {
910
+ end--;
911
+ }
912
+ if (end === lineEnd) {
913
+ return body.slice(0, end);
914
+ }
915
+ var backslashes = 0;
916
+ while (backslashes < end && body[end - backslashes - 1] === ESCAPE) {
917
+ backslashes++;
918
+ }
919
+ return backslashes % 2 ? body.slice(0, end - 1) + SPACE : body.slice(0, end);
920
+ };
904
921
  var createRule = function createRule(_ref3, ignoreCase) {
905
922
  var pattern = _ref3.pattern,
906
923
  mark = _ref3.mark;
924
+ // Git drops a BOM before it reads the first line, so before anything else.
925
+ var body = pattern[0] === BOM ? pattern.slice(1) : pattern;
926
+
927
+ // > A line starting with # serves as a comment.
928
+ if (body[0] === '#') {
929
+ return;
930
+ }
907
931
  var negative = false;
908
- var body = pattern;
909
932
 
910
933
  // > An optional prefix "!" which negates the pattern;
911
- if (body.indexOf('!') === 0) {
934
+ if (body[0] === '!') {
912
935
  negative = true;
913
- body = body.substr(1);
936
+ body = body.slice(1);
937
+ }
938
+
939
+ // Normalize the body before checking which slashes anchor the pattern.
940
+ // Otherwise `bar/ ` is mistaken for a pattern containing an inner slash.
941
+ // Only a body ending in a space or a line terminator has anything to trim.
942
+ var last = body[body.length - 1];
943
+ if (last === SPACE || last === '\r' || last === '\n') {
944
+ body = trimEnd(body);
945
+ }
946
+
947
+ // > A blank line matches no files, so it can serve as a separator for
948
+ // > readability.
949
+ // Nor does a lone "!", or anything else left empty here: an empty pattern
950
+ // would compile to a regex matching every path.
951
+ if (!body) {
952
+ return;
914
953
  }
915
954
  body = body
916
955
  // > Put a backslash ("\") in front of the first "!" for patterns that
@@ -958,8 +997,8 @@ var RuleManager = /*#__PURE__*/function () {
958
997
  pattern: pattern
959
998
  };
960
999
  }
961
- if (checkPattern(pattern.pattern)) {
962
- var rule = createRule(pattern, this._ignoreCase);
1000
+ var rule = checkPattern(pattern.pattern) && createRule(pattern, this._ignoreCase);
1001
+ if (rule) {
963
1002
  this._added = true;
964
1003
  this._rules.push(rule);
965
1004
 
@@ -978,9 +1017,44 @@ var RuleManager = /*#__PURE__*/function () {
978
1017
  value: function add(pattern) {
979
1018
  this._added = false;
980
1019
  makeArray(isString(pattern) ? splitPattern(pattern) : pattern).forEach(this._add, this);
1020
+ if (this._added) {
1021
+ this._literalRules = UNDEFINED;
1022
+ }
981
1023
  return this._added;
982
1024
  }
983
1025
 
1026
+ // Match the literal 'abc/' for `checkIgnore`, last rule wins. Only a rule
1027
+ // ending in a wildcard can match it (see `checkSourceOf`), so the rest
1028
+ // are left out once, rather than tested or compiled for every path.
1029
+ }, {
1030
+ key: "testLiteral",
1031
+ value: function testLiteral(path) {
1032
+ var rules = this._literalRules || (this._literalRules = this._rules.filter(function (_ref4) {
1033
+ var body = _ref4.body;
1034
+ return body[body.length - (body[body.length - 1] === SLASH ? 2 : 1)] === '*';
1035
+ }));
1036
+ var ignored = false;
1037
+ var unignored = false;
1038
+ var matchedRule;
1039
+ for (var index = rules.length - 1; index >= 0; index--) {
1040
+ var rule = rules[index];
1041
+ if (rule.checkRegex.test(path)) {
1042
+ ignored = !rule.negative;
1043
+ unignored = rule.negative;
1044
+ matchedRule = rule.negative ? UNDEFINED : rule;
1045
+ break;
1046
+ }
1047
+ }
1048
+ var ret = {
1049
+ ignored: ignored,
1050
+ unignored: unignored
1051
+ };
1052
+ if (matchedRule) {
1053
+ ret.rule = matchedRule;
1054
+ }
1055
+ return ret;
1056
+ }
1057
+
984
1058
  // Test one single path without recursively checking parent directories
985
1059
  //
986
1060
  // - checkUnignored `boolean` whether should check if the path is unignored,
@@ -1107,13 +1181,13 @@ checkPath.convert = function (p) {
1107
1181
  };
1108
1182
  var Ignore = /*#__PURE__*/function () {
1109
1183
  function Ignore() {
1110
- var _ref4 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
1111
- _ref4$ignorecase = _ref4.ignorecase,
1112
- ignorecase = _ref4$ignorecase === void 0 ? true : _ref4$ignorecase,
1113
- _ref4$ignoreCase = _ref4.ignoreCase,
1114
- ignoreCase = _ref4$ignoreCase === void 0 ? ignorecase : _ref4$ignoreCase,
1115
- _ref4$allowRelativePa = _ref4.allowRelativePaths,
1116
- allowRelativePaths = _ref4$allowRelativePa === void 0 ? false : _ref4$allowRelativePa;
1184
+ var _ref5 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
1185
+ _ref5$ignorecase = _ref5.ignorecase,
1186
+ ignorecase = _ref5$ignorecase === void 0 ? true : _ref5$ignorecase,
1187
+ _ref5$ignoreCase = _ref5.ignoreCase,
1188
+ ignoreCase = _ref5$ignoreCase === void 0 ? ignorecase : _ref5$ignoreCase,
1189
+ _ref5$allowRelativePa = _ref5.allowRelativePaths,
1190
+ allowRelativePaths = _ref5$allowRelativePa === void 0 ? false : _ref5$allowRelativePa;
1117
1191
  _classCallCheck(this, Ignore);
1118
1192
  define(this, KEY_IGNORE, true);
1119
1193
  this._rules = new RuleManager(ignoreCase);
@@ -1166,14 +1240,16 @@ var Ignore = /*#__PURE__*/function () {
1166
1240
  if (path.charCodeAt(path.length - 1) !== SLASH_CODE) {
1167
1241
  return this.test(path);
1168
1242
  }
1169
- var parentPath = parentOf(path);
1170
- if (parentPath) {
1171
- var parent = this._t(parentPath, this._testCache, true);
1172
- if (parent.ignored) {
1173
- return parent;
1174
- }
1243
+
1244
+ // Like `git check-ignore`: a directory excluded by itself or by an
1245
+ // ancestor settles it, and only then is the literal 'abc/' matched
1246
+ // against the rules (see `checkSourceOf`).
1247
+ var dir = this._t(path, this._testCache, true);
1248
+ if (dir.ignored) {
1249
+ return dir;
1175
1250
  }
1176
- return this._rules.test(path, false, MODE_CHECK_IGNORE);
1251
+ var literal = this._rules.testLiteral(path);
1252
+ return literal.ignored || literal.unignored ? literal : dir;
1177
1253
  }
1178
1254
  }, {
1179
1255
  key: "_t",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ignore",
3
- "version": "7.0.10",
3
+ "version": "7.0.12",
4
4
  "description": "Ignore is a manager and filter for .gitignore rules, the one used by eslint, gitbook and many others.",
5
5
  "types": "index.d.ts",
6
6
  "files": [
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mrclrchtr/supi-lsp",
3
- "version": "8.0.0",
3
+ "version": "9.0.0",
4
4
  "description": "Language Server Protocol runtime for SuPi code intelligence",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -37,8 +37,8 @@
37
37
  "vscode-jsonrpc": "^9.0.0",
38
38
  "vscode-languageserver-protocol": "^3.18.0",
39
39
  "vscode-languageserver-types": "^3.18.0",
40
- "@mrclrchtr/supi-code-runtime": "8.0.0",
41
- "@mrclrchtr/supi-core": "8.0.0"
40
+ "@mrclrchtr/supi-code-runtime": "9.0.0",
41
+ "@mrclrchtr/supi-core": "9.0.0"
42
42
  },
43
43
  "bundledDependencies": [
44
44
  "@mrclrchtr/supi-code-runtime",
@@ -78,6 +78,9 @@ import { JsonRpcClient, JsonRpcRequestError } from "./transport.ts";
78
78
 
79
79
  const SHUTDOWN_TIMEOUT_MS = 5_000;
80
80
 
81
+ /** Bounded stderr tail kept for startup-failure error messages. */
82
+ const STDERR_TAIL_MAX_CHARS = 4_000;
83
+
81
84
  interface SemanticRequestAttemptState {
82
85
  inputRevision: number | undefined;
83
86
  }
@@ -699,8 +702,13 @@ export class LspClient {
699
702
  this.handleProcessFailure(new Error("Client process error"));
700
703
  });
701
704
 
702
- // Suppress stderr to avoid noise in the agent
703
- this.process.stderr?.on("data", () => {});
705
+ // Capture a bounded stderr tail (discarded otherwise) so startup
706
+ // failures can surface the server's own exit reason — expired builds,
707
+ // missing runtimes, or invalid flags. Stderr never reaches the agent.
708
+ let stderrTail = "";
709
+ this.process.stderr?.on("data", (chunk: Buffer | string) => {
710
+ stderrTail = `${stderrTail}${chunk}`.slice(-STDERR_TAIL_MAX_CHARS);
711
+ });
704
712
 
705
713
  // Initialize handshake
706
714
  try {
@@ -736,7 +744,10 @@ export class LspClient {
736
744
 
737
745
  this.armNoProgressTimer();
738
746
  } catch (err) {
739
- const failure = new Error(`${this.name}: initialize failed: ${err}`, { cause: err });
747
+ const stderrDetail = stderrTail.trim() ? `\n${this.name} stderr:\n${stderrTail.trim()}` : "";
748
+ const failure = new Error(`${this.name}: initialize failed: ${err}${stderrDetail}`, {
749
+ cause: err,
750
+ });
740
751
  this.handleProcessFailure(failure);
741
752
  killFailedStartupProcess(this.process);
742
753
  throw failure;
@@ -77,6 +77,12 @@
77
77
  "args": ["--slave", "-e", "languageserver::run()"],
78
78
  "fileTypes": ["r"],
79
79
  "rootMarkers": ["DESCRIPTION", "renv.lock", ".Rprofile"]
80
+ },
81
+ "latex": {
82
+ "command": "texlab",
83
+ "args": [],
84
+ "fileTypes": ["tex", "bib"],
85
+ "rootMarkers": []
80
86
  }
81
87
  }
82
88
  }
@@ -1,6 +1,6 @@
1
1
  /** Reason for a partial or unavailable single-file result when the push stays tentative. */
2
2
  export const TENTATIVE_PUSH_UNAVAILABLE_REASON =
3
- "The current diagnostic publication is ambient evidence and cannot confirm the document synchronization.";
3
+ "A diagnostic publication is ambient evidence only; it may show issues, but an empty publication cannot confirm that the document is clean.";
4
4
 
5
5
  /** A final evidence state for one tracked document. */
6
6
  export type DiagnosticEvidenceStatus = "confirmed" | "unconfirmed" | "failed" | "removed";
@@ -2390,7 +2390,7 @@ export class LspManager {
2390
2390
  return Array.from(activeServers.entries())
2391
2391
  .map(([name, openFiles]) => ({
2392
2392
  name,
2393
- openFiles: Array.from(openFiles).sort(),
2393
+ openFiles: Array.from(openFiles).sort((left, right) => left.localeCompare(right)),
2394
2394
  }))
2395
2395
  .sort((a, b) => b.openFiles.length - a.openFiles.length || a.name.localeCompare(b.name));
2396
2396
  }
@@ -31,6 +31,7 @@ export async function runRenameRefactor(options: {
31
31
  return {
32
32
  kind: "unavailable",
33
33
  reason: response.reason ?? "No routed LSP client could plan the rename.",
34
+ authorizedMutationRoots: [...response.authorizedMutationRoots],
34
35
  };
35
36
  }
36
37
  return normalizeSemanticEdit(
@@ -133,7 +133,7 @@ function normalizeChanges(
133
133
  }
134
134
 
135
135
  const edits: FileEdit[] = [];
136
- for (const uri of Object.keys(changes).sort()) {
136
+ for (const uri of Object.keys(changes).sort((left, right) => left.localeCompare(right))) {
137
137
  const file = toFilePath(uri);
138
138
  const textEdits = changes[uri];
139
139
  if (!file) {
package/src/utils.ts CHANGED
@@ -53,6 +53,8 @@ const EXT_TO_LANGUAGE: Record<string, string> = {
53
53
  kts: "kotlin",
54
54
  swift: "swift",
55
55
  lua: "lua",
56
+ tex: "latex",
57
+ bib: "bibtex",
56
58
  zig: "zig",
57
59
  };
58
60