@mrclrchtr/supi-lsp 10.0.0 → 11.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +88 -2
- package/node_modules/@mrclrchtr/supi-code-runtime/node_modules/picomatch/LICENSE +21 -0
- package/node_modules/@mrclrchtr/supi-code-runtime/node_modules/picomatch/README.md +743 -0
- package/node_modules/@mrclrchtr/supi-code-runtime/node_modules/picomatch/index.js +17 -0
- package/node_modules/@mrclrchtr/supi-code-runtime/node_modules/picomatch/lib/constants.js +184 -0
- package/node_modules/@mrclrchtr/supi-code-runtime/node_modules/picomatch/lib/parse.js +1425 -0
- package/node_modules/@mrclrchtr/supi-code-runtime/node_modules/picomatch/lib/picomatch.js +361 -0
- package/node_modules/@mrclrchtr/supi-code-runtime/node_modules/picomatch/lib/scan.js +403 -0
- package/node_modules/@mrclrchtr/supi-code-runtime/node_modules/picomatch/lib/utils.js +72 -0
- package/node_modules/@mrclrchtr/supi-code-runtime/node_modules/picomatch/package.json +83 -0
- package/node_modules/@mrclrchtr/supi-code-runtime/node_modules/picomatch/posix.js +3 -0
- package/node_modules/@mrclrchtr/supi-code-runtime/package.json +4 -1
- package/node_modules/@mrclrchtr/supi-code-runtime/src/api.ts +11 -0
- package/node_modules/@mrclrchtr/supi-code-runtime/src/file-associations.ts +190 -0
- package/node_modules/@mrclrchtr/supi-code-runtime/src/types.ts +22 -0
- package/node_modules/@mrclrchtr/supi-core/package.json +1 -1
- package/node_modules/ignore/README.md +61 -6
- package/node_modules/ignore/index.d.ts +55 -20
- package/node_modules/ignore/index.js +93 -67
- package/node_modules/ignore/legacy.js +109 -85
- package/node_modules/ignore/package.json +1 -1
- package/package.json +3 -3
- package/src/api.ts +1 -0
- package/src/client/client-diagnostic-host.ts +3 -0
- package/src/client/client-diagnostics.ts +6 -4
- package/src/client/client-request-enrollment.ts +66 -22
- package/src/client/client-semantic-input-barrier.ts +37 -5
- package/src/client/client.ts +136 -43
- package/src/manager/manager.ts +261 -22
- package/src/provider/refactor-planning.ts +13 -0
- package/src/provider/semantic-edit-discovery.ts +151 -0
- package/src/provider/semantic-edit-normalizer.ts +97 -129
- package/src/provider/semantic-edit-protocol.ts +132 -0
- package/src/session/runtime-controller.ts +8 -1
- package/src/session/runtime-registry.ts +7 -20
- package/src/session/runtime-rename.ts +172 -0
- package/src/session/workspace-lsp-runtime.ts +14 -0
- package/src/utils.ts +12 -11
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
import * as path from "node:path";
|
|
2
|
+
import picomatch from "picomatch";
|
|
3
|
+
|
|
4
|
+
/** Language selected for a C-family source file. */
|
|
5
|
+
export type CFamilyLanguage = "c" | "cpp";
|
|
6
|
+
|
|
7
|
+
/** One ordered, project-relative language rule for an existing C-family file. */
|
|
8
|
+
export interface CFamilyFileAssociationRule {
|
|
9
|
+
readonly pattern: string;
|
|
10
|
+
readonly language: CFamilyLanguage;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/** C-family suffixes that already have Tree-sitter and LSP support. */
|
|
14
|
+
export const C_FAMILY_EXTENSIONS = Object.freeze([
|
|
15
|
+
".c",
|
|
16
|
+
".h",
|
|
17
|
+
".cpp",
|
|
18
|
+
".hpp",
|
|
19
|
+
".cc",
|
|
20
|
+
".cxx",
|
|
21
|
+
".hxx",
|
|
22
|
+
".c++",
|
|
23
|
+
".h++",
|
|
24
|
+
] as const);
|
|
25
|
+
|
|
26
|
+
export type CFamilyExtension = (typeof C_FAMILY_EXTENSIONS)[number];
|
|
27
|
+
|
|
28
|
+
const DEFAULT_C_FAMILY_LANGUAGES: Readonly<Record<CFamilyExtension, CFamilyLanguage>> =
|
|
29
|
+
Object.freeze({
|
|
30
|
+
".c": "c",
|
|
31
|
+
".h": "c",
|
|
32
|
+
".cpp": "cpp",
|
|
33
|
+
".hpp": "cpp",
|
|
34
|
+
".cc": "cpp",
|
|
35
|
+
".cxx": "cpp",
|
|
36
|
+
".hxx": "cpp",
|
|
37
|
+
".c++": "cpp",
|
|
38
|
+
".h++": "cpp",
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
/** Immutable C-family language selection for one workspace. */
|
|
42
|
+
export interface CFamilyFileAssociationResolver {
|
|
43
|
+
/** Absolute root used to make project-relative paths. */
|
|
44
|
+
readonly workspaceRoot: string;
|
|
45
|
+
/** Validated ordered rules captured when the workspace host starts. */
|
|
46
|
+
readonly rules: readonly CFamilyFileAssociationRule[];
|
|
47
|
+
/** Select the configured language or the existing suffix default. */
|
|
48
|
+
languageForFile(filePath: string): CFamilyLanguage | undefined;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/** Return the current default language for one supported C-family suffix. */
|
|
52
|
+
export function defaultCFamilyLanguage(extension: string): CFamilyLanguage | undefined {
|
|
53
|
+
return DEFAULT_C_FAMILY_LANGUAGES[extension.toLowerCase() as CFamilyExtension];
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Validate and compile ordered C-family file associations for one workspace.
|
|
58
|
+
* Patterns are case-sensitive globs over POSIX-style, workspace-relative paths.
|
|
59
|
+
* Supported patterns use `*`, `?`, `**`, character classes, and brace alternatives.
|
|
60
|
+
* The first matching rule wins. Rules never expand the eligible suffix set.
|
|
61
|
+
*
|
|
62
|
+
* @throws If the rule list, a rule, a language, or a pattern is invalid.
|
|
63
|
+
*/
|
|
64
|
+
export function createCFamilyFileAssociationResolver(
|
|
65
|
+
workspaceRoot: string,
|
|
66
|
+
input: unknown = [],
|
|
67
|
+
): CFamilyFileAssociationResolver {
|
|
68
|
+
const rules = validateRules(input);
|
|
69
|
+
const matchers = rules.map((rule, index) => ({
|
|
70
|
+
language: rule.language,
|
|
71
|
+
matches: compilePattern(rule.pattern, `code-intelligence.fileAssociations[${index}]`),
|
|
72
|
+
}));
|
|
73
|
+
const root = path.resolve(workspaceRoot);
|
|
74
|
+
return Object.freeze({
|
|
75
|
+
workspaceRoot: root,
|
|
76
|
+
rules,
|
|
77
|
+
languageForFile(filePath: string): CFamilyLanguage | undefined {
|
|
78
|
+
const extension = normalizeExtension(filePath);
|
|
79
|
+
const fallback = defaultCFamilyLanguage(extension);
|
|
80
|
+
if (!fallback) return undefined;
|
|
81
|
+
|
|
82
|
+
const absolutePath = path.resolve(root, filePath);
|
|
83
|
+
const relativePath = toPosixPath(path.relative(root, absolutePath));
|
|
84
|
+
if (
|
|
85
|
+
relativePath === ".." ||
|
|
86
|
+
relativePath.startsWith("../") ||
|
|
87
|
+
path.posix.isAbsolute(relativePath)
|
|
88
|
+
) {
|
|
89
|
+
return fallback;
|
|
90
|
+
}
|
|
91
|
+
for (const rule of matchers) {
|
|
92
|
+
if (rule.matches(relativePath)) return rule.language;
|
|
93
|
+
}
|
|
94
|
+
return fallback;
|
|
95
|
+
},
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
function validateRules(input: unknown): readonly CFamilyFileAssociationRule[] {
|
|
100
|
+
if (!Array.isArray(input)) {
|
|
101
|
+
throw new Error('Invalid "code-intelligence.fileAssociations": expected an ordered array.');
|
|
102
|
+
}
|
|
103
|
+
if (input.length > 64) {
|
|
104
|
+
throw new Error('Invalid "code-intelligence.fileAssociations": use no more than 64 rules.');
|
|
105
|
+
}
|
|
106
|
+
const rules: CFamilyFileAssociationRule[] = [];
|
|
107
|
+
const seenPatterns = new Set<string>();
|
|
108
|
+
for (const [index, value] of input.entries()) {
|
|
109
|
+
const key = `code-intelligence.fileAssociations[${index}]`;
|
|
110
|
+
if (!isRecord(value) || !hasExactKeys(value, ["pattern", "language"])) {
|
|
111
|
+
throw new Error(`${key} must contain only "pattern" and "language" fields.`);
|
|
112
|
+
}
|
|
113
|
+
if (typeof value.pattern !== "string") {
|
|
114
|
+
throw new Error(`${key}.pattern must be a string.`);
|
|
115
|
+
}
|
|
116
|
+
if (value.language !== "c" && value.language !== "cpp") {
|
|
117
|
+
throw new Error(`${key}.language must be "c" or "cpp".`);
|
|
118
|
+
}
|
|
119
|
+
if (seenPatterns.has(value.pattern)) {
|
|
120
|
+
throw new Error(`${key}.pattern duplicates an earlier rule.`);
|
|
121
|
+
}
|
|
122
|
+
seenPatterns.add(value.pattern);
|
|
123
|
+
rules.push(Object.freeze({ pattern: value.pattern, language: value.language }));
|
|
124
|
+
}
|
|
125
|
+
return Object.freeze(rules);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
function compilePattern(pattern: string, key: string): (file: string) => boolean {
|
|
129
|
+
if (
|
|
130
|
+
pattern.length === 0 ||
|
|
131
|
+
pattern.length > 512 ||
|
|
132
|
+
pattern !== pattern.trim() ||
|
|
133
|
+
pattern.includes("\\") ||
|
|
134
|
+
hasControlCharacter(pattern) ||
|
|
135
|
+
pattern.startsWith("/") ||
|
|
136
|
+
/^[A-Za-z]:/.test(pattern) ||
|
|
137
|
+
pattern.startsWith("!")
|
|
138
|
+
) {
|
|
139
|
+
throw new Error(`${key}.pattern must be a safe workspace-relative glob using "/" separators.`);
|
|
140
|
+
}
|
|
141
|
+
const segments = pattern.split("/");
|
|
142
|
+
if (segments.some((segment) => segment === "" || segment === "." || segment === "..")) {
|
|
143
|
+
throw new Error(`${key}.pattern contains an unsafe or unsupported path pattern.`);
|
|
144
|
+
}
|
|
145
|
+
try {
|
|
146
|
+
return picomatch(pattern, {
|
|
147
|
+
nocase: false,
|
|
148
|
+
windows: false,
|
|
149
|
+
dot: true,
|
|
150
|
+
strictBrackets: true,
|
|
151
|
+
nonegate: true,
|
|
152
|
+
noextglob: true,
|
|
153
|
+
maxLength: 512,
|
|
154
|
+
});
|
|
155
|
+
} catch (error) {
|
|
156
|
+
throw new Error(`${key}.pattern is not a valid glob: ${errorMessage(error)}`, { cause: error });
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
function hasControlCharacter(value: string): boolean {
|
|
161
|
+
for (const character of value) {
|
|
162
|
+
const code = character.charCodeAt(0);
|
|
163
|
+
if (code < 32 || code === 127) return true;
|
|
164
|
+
}
|
|
165
|
+
return false;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
function normalizeExtension(filePath: string): string {
|
|
169
|
+
return path.posix.extname(toPosixPath(filePath)).toLowerCase();
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
function toPosixPath(value: string): string {
|
|
173
|
+
return value.replaceAll("\\", "/");
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
177
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
function hasExactKeys(value: Record<string, unknown>, keys: readonly string[]): boolean {
|
|
181
|
+
const allowed = new Set(keys);
|
|
182
|
+
return (
|
|
183
|
+
keys.every((key) => Object.hasOwn(value, key)) &&
|
|
184
|
+
Object.keys(value).every((key) => allowed.has(key))
|
|
185
|
+
);
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
function errorMessage(error: unknown): string {
|
|
189
|
+
return error instanceof Error ? error.message : String(error);
|
|
190
|
+
}
|
|
@@ -80,6 +80,14 @@ export interface DocumentCodeSymbol extends CodeSymbol {
|
|
|
80
80
|
*/
|
|
81
81
|
export type CodeResult<T> =
|
|
82
82
|
| { kind: "success"; data: T }
|
|
83
|
+
| {
|
|
84
|
+
kind: "partial";
|
|
85
|
+
data: T;
|
|
86
|
+
file: string;
|
|
87
|
+
reason: string;
|
|
88
|
+
/** Syntax error and missing-node ranges in 0-based UTF-16 coordinates. */
|
|
89
|
+
errorRanges: SourceRange[];
|
|
90
|
+
}
|
|
83
91
|
| { kind: "unsupported-language"; file: string; message: string }
|
|
84
92
|
| { kind: "file-access-error"; file: string; message: string }
|
|
85
93
|
| { kind: "validation-error"; message: string }
|
|
@@ -93,7 +101,10 @@ export type ConfidenceMode = "semantic" | "structural" | "heuristic" | "unavaila
|
|
|
93
101
|
|
|
94
102
|
export interface OutlineData {
|
|
95
103
|
name: string;
|
|
104
|
+
/** Common structural search category. */
|
|
96
105
|
kind: string;
|
|
106
|
+
/** Source-language declaration kind, separate from common search category. */
|
|
107
|
+
nativeKind?: string;
|
|
97
108
|
/** Exact 1-based start of the declaration name token, when known. */
|
|
98
109
|
nameAnchor?: SymbolAnchor;
|
|
99
110
|
/** Exclusive 1-based end of a verified literal name span, when known. */
|
|
@@ -156,6 +167,12 @@ export interface FileEdit {
|
|
|
156
167
|
/** A document-state precondition established when semantic edits are normalized. */
|
|
157
168
|
export type DocumentEditPrecondition =
|
|
158
169
|
| { file: string; kind: "open-document-version"; version: number }
|
|
170
|
+
| {
|
|
171
|
+
file: string;
|
|
172
|
+
kind: "open-document-content";
|
|
173
|
+
version: number;
|
|
174
|
+
fingerprint: string;
|
|
175
|
+
}
|
|
159
176
|
| { file: string; kind: "disk-content" };
|
|
160
177
|
|
|
161
178
|
/**
|
|
@@ -257,5 +274,10 @@ export interface CalleesData {
|
|
|
257
274
|
/** A single call-site match with name and start line. */
|
|
258
275
|
export interface CallSite {
|
|
259
276
|
name: string;
|
|
277
|
+
/** 1-based UTF-16 start position of the written callee expression. */
|
|
260
278
|
startLine: number;
|
|
279
|
+
startCharacter: number;
|
|
280
|
+
/** Exclusive 1-based UTF-16 end position of the captured source expression. */
|
|
281
|
+
endLine: number;
|
|
282
|
+
endCharacter: number;
|
|
261
283
|
}
|
|
@@ -173,6 +173,29 @@ ig.ignores(path.join('./abc')) // path.join('./abc') -> 'abc'
|
|
|
173
173
|
|
|
174
174
|
In other words, each `Pathname` here should be a relative path to the directory of the gitignore rules.
|
|
175
175
|
|
|
176
|
+
A `.` or `..` component anywhere else in a `Pathname` is outside the
|
|
177
|
+
convention as well, though no error is thrown for it: the check reads how the
|
|
178
|
+
path starts, so that it costs nothing on a hot path. `path.relative()` never
|
|
179
|
+
produces such a component, and one that carries it is not matched the way
|
|
180
|
+
`git` matches it — `git` drops the component from the path first, `ignore`
|
|
181
|
+
matches the path as it was given.
|
|
182
|
+
|
|
183
|
+
```js
|
|
184
|
+
// path.relative('/', '/a/./b') -> 'a/b'
|
|
185
|
+
|
|
186
|
+
// Right
|
|
187
|
+
ignore().add('a/b').ignores('a/b') // true
|
|
188
|
+
|
|
189
|
+
// Outside the convention: git matches 'a/b' here and so says true
|
|
190
|
+
ignore().add('a/b').ignores('a/./b') // false
|
|
191
|
+
|
|
192
|
+
// Outside the convention: git matches 'a' here and so says false
|
|
193
|
+
ignore().add('a/.').ignores('a/.') // true
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
A rule that matches an ancestor still agrees, since the component makes no
|
|
197
|
+
difference to it: `add('a').ignores('a/./b')` is `true` either way.
|
|
198
|
+
|
|
176
199
|
Suppose the dir structure is:
|
|
177
200
|
|
|
178
201
|
```
|
|
@@ -265,7 +288,8 @@ Returns `TestResult`
|
|
|
265
288
|
// Since 5.0.0
|
|
266
289
|
interface TestResult {
|
|
267
290
|
ignored: boolean
|
|
268
|
-
// true if the `pathname`
|
|
291
|
+
// true if a negative pattern matched the `pathname` itself, and no parent
|
|
292
|
+
// directory of it is ignored -- see "When both are false" below
|
|
269
293
|
unignored: boolean
|
|
270
294
|
// The `IgnoreRule` which ignores the pathname
|
|
271
295
|
rule?: IgnoreRule
|
|
@@ -283,8 +307,39 @@ interface IgnoreRule {
|
|
|
283
307
|
```
|
|
284
308
|
|
|
285
309
|
- `{ignored: true, unignored: false}`: the `pathname` is ignored
|
|
286
|
-
- `{ignored: false, unignored: true}`: the `pathname`
|
|
287
|
-
- `{ignored: false, unignored: false}`: the `pathname`
|
|
310
|
+
- `{ignored: false, unignored: true}`: a negative pattern matched the `pathname` itself
|
|
311
|
+
- `{ignored: false, unignored: false}`: no rule matched the `pathname` itself, and no parent directory of it is ignored
|
|
312
|
+
|
|
313
|
+
### When both are `false`
|
|
314
|
+
|
|
315
|
+
`{ignored: false, unignored: false}` covers two different situations:
|
|
316
|
+
|
|
317
|
+
- no rule matched the `pathname`, nor any of its parent directories, or
|
|
318
|
+
- no rule matched the `pathname` itself, but one of its parent directories is unignored by a negative pattern: the `pathname` is unignored **indirectly**.
|
|
319
|
+
|
|
320
|
+
`unignored` stays `false` in the second case because only `ignored` passes down from a parent directory. A `pathname` whose parent directory is ignored is ignored as well — git never re-includes a file whose parent directory is excluded — but one whose parent directory is unignored is decided on its own, by the rules that match the `pathname` itself.
|
|
321
|
+
|
|
322
|
+
```js
|
|
323
|
+
const ig2 = ignore().add([
|
|
324
|
+
'foo*',
|
|
325
|
+
'!foobar'
|
|
326
|
+
])
|
|
327
|
+
|
|
328
|
+
// The directory `foobar/` is unignored directly, by `!foobar`
|
|
329
|
+
ig2.test('foobar/') // {ignored: false, unignored: true}
|
|
330
|
+
|
|
331
|
+
// No rule matches `foobar/x.js` itself. It is not ignored only because its
|
|
332
|
+
// parent directory `foobar/` is not, so it is unignored indirectly
|
|
333
|
+
ig2.test('foobar/x.js') // {ignored: false, unignored: false}
|
|
334
|
+
```
|
|
335
|
+
|
|
336
|
+
To tell the two situations apart, test the parent directories of the `pathname`, each with a trailing slash: the `pathname` is unignored indirectly if any of them is `unignored`.
|
|
337
|
+
|
|
338
|
+
```js
|
|
339
|
+
['foobar/'].some(dir => ig2.test(dir).unignored) // true
|
|
340
|
+
```
|
|
341
|
+
|
|
342
|
+
`unignored` is meant for packages that implement their own caching mechanism upon `node-ignore`. To simply tell whether a `pathname` is ignored, use `.ignores()` or check `TestResult::ignored`.
|
|
288
343
|
|
|
289
344
|
## .checkIgnore(target: string): TestResult
|
|
290
345
|
|
|
@@ -294,7 +349,7 @@ Debugs gitignore / exclude files, which is equivalent to `git check-ignore -v`.
|
|
|
294
349
|
|
|
295
350
|
- **target** `string` the target to test.
|
|
296
351
|
|
|
297
|
-
Returns `TestResult`
|
|
352
|
+
Returns `TestResult`, the same shape `.test()` returns, so `{ignored: false, unignored: false}` carries the [same two meanings](#when-both-are-false) here.
|
|
298
353
|
|
|
299
354
|
```js
|
|
300
355
|
ig.add({
|
|
@@ -305,10 +360,10 @@ ig.add({
|
|
|
305
360
|
const {
|
|
306
361
|
ignored,
|
|
307
362
|
rule
|
|
308
|
-
} = checkIgnore('foo/')
|
|
363
|
+
} = ig.checkIgnore('foo/')
|
|
309
364
|
|
|
310
365
|
if (ignored) {
|
|
311
|
-
console.log(`.gitignore:${
|
|
366
|
+
console.log(`.gitignore:${rule.mark}:${rule.pattern} foo/`)
|
|
312
367
|
}
|
|
313
368
|
|
|
314
369
|
// .gitignore:60:foo/* foo/
|
|
@@ -1,27 +1,61 @@
|
|
|
1
|
-
type Pathname = string
|
|
2
|
-
|
|
3
|
-
interface IgnoreRule {
|
|
4
|
-
pattern: string
|
|
5
|
-
mark?: string
|
|
6
|
-
negative: boolean
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
interface TestResult {
|
|
10
|
-
ignored: boolean
|
|
11
|
-
unignored: boolean
|
|
12
|
-
rule?: IgnoreRule
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
interface PatternParams {
|
|
16
|
-
pattern: string
|
|
17
|
-
mark?: string
|
|
18
|
-
}
|
|
19
|
-
|
|
20
1
|
/**
|
|
21
2
|
* Creates new ignore manager.
|
|
22
3
|
*/
|
|
23
4
|
declare function ignore(options?: ignore.Options): ignore.Ignore
|
|
24
5
|
declare namespace ignore {
|
|
6
|
+
/**
|
|
7
|
+
* A path relative to the directory the rules belong to, as
|
|
8
|
+
* `path.relative()` returns it.
|
|
9
|
+
*/
|
|
10
|
+
type Pathname = string
|
|
11
|
+
|
|
12
|
+
interface PatternParams {
|
|
13
|
+
pattern: string
|
|
14
|
+
/**
|
|
15
|
+
* Carried through to `IgnoreRule.mark`, for packages that build upon
|
|
16
|
+
* `ignore`.
|
|
17
|
+
*/
|
|
18
|
+
mark?: string
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
interface IgnoreRule {
|
|
22
|
+
/**
|
|
23
|
+
* The original pattern.
|
|
24
|
+
*/
|
|
25
|
+
pattern: string
|
|
26
|
+
/**
|
|
27
|
+
* Carried through from `PatternParams.mark`.
|
|
28
|
+
*/
|
|
29
|
+
mark?: string
|
|
30
|
+
/**
|
|
31
|
+
* Whether the pattern is a negative one, such as `!foo`.
|
|
32
|
+
*/
|
|
33
|
+
negative: boolean
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
interface TestResult {
|
|
37
|
+
/**
|
|
38
|
+
* Whether the pathname is ignored, by a rule or because a parent
|
|
39
|
+
* directory of it is.
|
|
40
|
+
*/
|
|
41
|
+
ignored: boolean
|
|
42
|
+
/**
|
|
43
|
+
* True if a negative pattern matched the pathname itself, and no parent
|
|
44
|
+
* directory of it is ignored.
|
|
45
|
+
*
|
|
46
|
+
* Only `ignored` passes down from a parent directory, so a pathname that
|
|
47
|
+
* is not ignored only because a parent directory was unignored keeps
|
|
48
|
+
* this false, as does one no rule applies to at all. To tell those two
|
|
49
|
+
* apart, test the parent directories, each with a trailing slash.
|
|
50
|
+
*/
|
|
51
|
+
unignored: boolean
|
|
52
|
+
/**
|
|
53
|
+
* The rule that ignores the pathname. Present exactly when `ignored` is
|
|
54
|
+
* true.
|
|
55
|
+
*/
|
|
56
|
+
rule?: IgnoreRule
|
|
57
|
+
}
|
|
58
|
+
|
|
25
59
|
interface Ignore {
|
|
26
60
|
/**
|
|
27
61
|
* Adds one or several rules to the current manager.
|
|
@@ -54,7 +88,8 @@ declare namespace ignore {
|
|
|
54
88
|
ignores(pathname: Pathname): boolean
|
|
55
89
|
|
|
56
90
|
/**
|
|
57
|
-
*
|
|
91
|
+
* Tests the pathname against the rules. `ignored` and `unignored` can
|
|
92
|
+
* both be false: see `TestResult.unignored` for the two cases.
|
|
58
93
|
* @param {string} pathname a path to check
|
|
59
94
|
* @returns TestResult
|
|
60
95
|
*/
|