@adecore/editor-react 0.31.12 → 0.32.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/AnchoredPopup.js +73 -19
- package/dist/AttributionCard.js +162 -4
- package/dist/BaselineStatus.js +62 -8
- package/dist/CallHierarchyPanel.js +977 -60
- package/dist/ChangeReview.js +76 -25
- package/dist/CodeAuthorsCard.js +314 -14
- package/dist/CompletionPopup.js +490 -83
- package/dist/DiffView.js +548 -181
- package/dist/EditorContextMenu.js +352 -34
- package/dist/EditorView.js +276 -99
- package/dist/FindReplace.js +525 -67
- package/dist/HoverCard.js +378 -38
- package/dist/HoverSections.js +367 -56
- package/dist/LanguagePopups.js +95 -34
- package/dist/Markdown.js +41 -6
- package/dist/PanelResizeHandle.js +199 -66
- package/dist/PathText.js +49 -7
- package/dist/PeekPanel.js +675 -72
- package/dist/PickPopup.js +304 -34
- package/dist/RenameCard.js +679 -85
- package/dist/RenderedDocs.js +329 -58
- package/dist/SignatureCard.js +91 -7
- package/dist/SplitDiffView.js +344 -254
- package/dist/SymbolPicker.js +440 -85
- package/dist/call-hierarchy-model.js +102 -68
- package/dist/call-hierarchy.js +458 -359
- package/dist/code-actions-model.js +88 -76
- package/dist/code-actions.js +372 -283
- package/dist/code-authors.js +64 -55
- package/dist/code-vision-model.js +134 -127
- package/dist/code-vision.js +224 -206
- package/dist/completion-call.js +94 -67
- package/dist/completion-model.js +334 -244
- package/dist/completion.js +840 -649
- package/dist/conflict-model.js +35 -29
- package/dist/context-menu-rows.js +42 -17
- package/dist/context-menu.js +64 -46
- package/dist/definition-link.js +88 -85
- package/dist/diagnostics-model.js +74 -55
- package/dist/diagnostics.js +121 -100
- package/dist/diff-expansion.js +38 -35
- package/dist/diff-overlays.js +144 -22
- package/dist/diff-syntax.js +65 -42
- package/dist/diff-wordmarks.js +26 -23
- package/dist/doc-comment-model.js +265 -216
- package/dist/editor-language.js +177 -152
- package/dist/error-message.js +2 -2
- package/dist/find-query.js +49 -36
- package/dist/folding.js +81 -62
- package/dist/format-on-type.js +86 -67
- package/dist/highlight-layers.js +19 -20
- package/dist/highlights.js +105 -83
- package/dist/history.js +44 -38
- package/dist/holder.js +18 -18
- package/dist/host-types.js +1 -1
- package/dist/hover-content.js +167 -129
- package/dist/hover.js +285 -245
- package/dist/index.js +10 -10
- package/dist/inlay-hints.js +369 -324
- package/dist/key-priority.js +34 -31
- package/dist/language-ids.js +45 -42
- package/dist/line-edits.js +74 -28
- package/dist/line-text.js +18 -3
- package/dist/locales/en.json +38 -38
- package/dist/locales/nl.json +41 -41
- package/dist/models.js +1 -1
- package/dist/navigation-history.js +40 -41
- package/dist/navigation.js +141 -123
- package/dist/panel-size.js +8 -8
- package/dist/patch-decorations.js +236 -160
- package/dist/patch-layout.js +331 -262
- package/dist/paths.js +3 -3
- package/dist/peek-model.js +86 -69
- package/dist/peek.js +254 -192
- package/dist/pick.js +164 -157
- package/dist/popup-focus.js +5 -5
- package/dist/popup-placement.js +36 -21
- package/dist/popups.js +13 -13
- package/dist/project-language.js +228 -211
- package/dist/project-problems.js +81 -69
- package/dist/proposal-model.js +163 -126
- package/dist/recent-choices.js +25 -25
- package/dist/refresher.js +44 -49
- package/dist/rename-model.js +113 -113
- package/dist/rename.js +321 -233
- package/dist/rendered-docs.d.ts +4 -2
- package/dist/rendered-docs.js +384 -318
- package/dist/rendering-context.js +5 -3
- package/dist/rendering.js +22 -4
- package/dist/review-group.js +42 -39
- package/dist/row-host.d.ts +4 -2
- package/dist/row-host.js +90 -78
- package/dist/selection-ranges.js +21 -17
- package/dist/semantic-delta.js +22 -19
- package/dist/semantic-model.js +86 -73
- package/dist/semantic-tokens.js +201 -162
- package/dist/shortcut-keys.js +16 -10
- package/dist/signature-model.js +34 -28
- package/dist/signature.js +177 -129
- package/dist/snippet-field-transforms.js +118 -106
- package/dist/snippet-indent.js +48 -43
- package/dist/snippet-range-order.js +11 -11
- package/dist/snippet-session.js +703 -667
- package/dist/snippet-transform-client.js +59 -59
- package/dist/snippet-transform-format.js +285 -263
- package/dist/snippet-transform-protocol.js +1 -1
- package/dist/snippet-transform-queue.js +163 -153
- package/dist/snippet-transform-worker.js +42 -35
- package/dist/snippet-variable-names.js +1 -36
- package/dist/snippet-variables.js +53 -63
- package/dist/snippet.js +477 -405
- package/dist/split-alignment.js +47 -35
- package/dist/split-scroll.js +42 -40
- package/dist/symbol-links.js +33 -25
- package/dist/symbol-picker-model.js +126 -116
- package/dist/symbol-picker.js +98 -59
- package/dist/symbols.js +117 -88
- package/dist/testing.js +248 -165
- package/dist/timers.js +35 -30
- package/dist/use-panel-body.js +49 -8
- package/dist/use-problem-counts.js +29 -15
- package/dist/view-state.js +54 -33
- package/dist/word-diff.js +18 -18
- package/dist/workspace-edit.js +300 -249
- package/package.json +6 -6
- package/src/CallHierarchyPanel.tsx +2 -2
- package/src/DiffView.tsx +3 -3
- package/src/FindReplace.tsx +2 -2
- package/src/LanguagePopups.tsx +2 -0
- package/src/PeekPanel.tsx +3 -3
- package/src/RenderedDocs.tsx +9 -10
- package/src/SymbolPicker.tsx +2 -2
- package/src/diff-overlays.tsx +6 -4
- package/src/locales/en.json +38 -38
- package/src/locales/nl.json +41 -41
- package/src/rendered-docs.ts +14 -3
- package/src/row-host.ts +14 -3
package/dist/split-alignment.js
CHANGED
|
@@ -1,38 +1,50 @@
|
|
|
1
1
|
/* Intrinsic heights exclude spacers, so repeated alignment converges without adding its own padding. */
|
|
2
2
|
export function splitAlignment(aligned, oldHeight, newHeight, gapHeight = 32) {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
}
|
|
15
|
-
else {
|
|
16
|
-
rows[side].push({ id: gap === undefined ? `spacer-${index}` : `gap-${gap}`, line, placement, height, fixed: true, filler: gap === undefined });
|
|
17
|
-
}
|
|
18
|
-
};
|
|
19
|
-
for (const [index, entry] of aligned.entries()) {
|
|
20
|
-
if (entry.kind === 'gap') {
|
|
21
|
-
add('old', index, gapHeight, entry.row.id);
|
|
22
|
-
add('new', index, gapHeight, entry.row.id);
|
|
23
|
-
continue;
|
|
24
|
-
}
|
|
25
|
-
const old = entry.old === undefined ? 0 : oldHeight(entry.old);
|
|
26
|
-
const fresh = entry.new === undefined ? 0 : newHeight(entry.new);
|
|
27
|
-
if (entry.old !== undefined) {
|
|
28
|
-
previous.old = entry.old;
|
|
29
|
-
}
|
|
30
|
-
if (entry.new !== undefined) {
|
|
31
|
-
previous.new = entry.new;
|
|
32
|
-
}
|
|
33
|
-
const target = Math.max(old, fresh);
|
|
34
|
-
add('old', index, target - old);
|
|
35
|
-
add('new', index, target - fresh);
|
|
3
|
+
const rows = {
|
|
4
|
+
old: [],
|
|
5
|
+
new: []
|
|
6
|
+
};
|
|
7
|
+
const previous = {
|
|
8
|
+
old: -1,
|
|
9
|
+
new: -1
|
|
10
|
+
};
|
|
11
|
+
const add = (side, index, height, gap) => {
|
|
12
|
+
if (height <= 0) {
|
|
13
|
+
return;
|
|
36
14
|
}
|
|
37
|
-
|
|
38
|
-
|
|
15
|
+
const line = Math.max(0, previous[side]);
|
|
16
|
+
const placement = previous[side] < 0 ? 'above' : 'below';
|
|
17
|
+
const last = rows[side].at(-1);
|
|
18
|
+
if (gap === undefined && last?.filler && last.line === line && last.placement === placement) {
|
|
19
|
+
last.height += height;
|
|
20
|
+
} else {
|
|
21
|
+
rows[side].push({
|
|
22
|
+
id: gap === undefined ? `spacer-${index}` : `gap-${gap}`,
|
|
23
|
+
line,
|
|
24
|
+
placement,
|
|
25
|
+
height,
|
|
26
|
+
fixed: true,
|
|
27
|
+
filler: gap === undefined
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
for (const [index, entry] of aligned.entries()) {
|
|
32
|
+
if (entry.kind === 'gap') {
|
|
33
|
+
add('old', index, gapHeight, entry.row.id);
|
|
34
|
+
add('new', index, gapHeight, entry.row.id);
|
|
35
|
+
continue;
|
|
36
|
+
}
|
|
37
|
+
const old = entry.old === undefined ? 0 : oldHeight(entry.old);
|
|
38
|
+
const fresh = entry.new === undefined ? 0 : newHeight(entry.new);
|
|
39
|
+
if (entry.old !== undefined) {
|
|
40
|
+
previous.old = entry.old;
|
|
41
|
+
}
|
|
42
|
+
if (entry.new !== undefined) {
|
|
43
|
+
previous.new = entry.new;
|
|
44
|
+
}
|
|
45
|
+
const target = Math.max(old, fresh);
|
|
46
|
+
add('old', index, target - old);
|
|
47
|
+
add('new', index, target - fresh);
|
|
48
|
+
}
|
|
49
|
+
return rows;
|
|
50
|
+
}
|
package/dist/split-scroll.js
CHANGED
|
@@ -1,45 +1,47 @@
|
|
|
1
1
|
export class SplitScroll {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
2
|
+
leader = 'new';
|
|
3
|
+
syncing = false;
|
|
4
|
+
expected;
|
|
5
|
+
editors;
|
|
6
|
+
constructor(editors) {
|
|
7
|
+
this.editors = editors;
|
|
8
|
+
this.expected = {
|
|
9
|
+
old: editors.old.getScrollTop(),
|
|
10
|
+
new: editors.new.getScrollTop()
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
drive(side) {
|
|
14
|
+
this.leader = side;
|
|
15
|
+
}
|
|
16
|
+
changed(side) {
|
|
17
|
+
if (this.syncing) {
|
|
18
|
+
return;
|
|
9
19
|
}
|
|
10
|
-
|
|
11
|
-
|
|
20
|
+
const top = this.editors[side].getScrollTop();
|
|
21
|
+
if (side !== this.leader) {
|
|
22
|
+
// Native scroll echoes arrive after setScrollTop returns, including a clamped follower position.
|
|
23
|
+
if (Math.abs(top - this.expected[side]) < 1) {
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
this.leader = side;
|
|
12
27
|
}
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
this.leader = side;
|
|
24
|
-
}
|
|
25
|
-
this.sync();
|
|
28
|
+
this.sync();
|
|
29
|
+
}
|
|
30
|
+
sync() {
|
|
31
|
+
const side = this.leader;
|
|
32
|
+
const other = side === 'old' ? 'new' : 'old';
|
|
33
|
+
const top = this.editors[side].getScrollTop();
|
|
34
|
+
this.expected[side] = top;
|
|
35
|
+
if (Math.abs(this.editors[other].getScrollTop() - top) < 1) {
|
|
36
|
+
this.expected[other] = this.editors[other].getScrollTop();
|
|
37
|
+
return;
|
|
26
38
|
}
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
this.expected[other] = this.editors[other].getScrollTop();
|
|
34
|
-
return;
|
|
35
|
-
}
|
|
36
|
-
this.syncing = true;
|
|
37
|
-
try {
|
|
38
|
-
this.editors[other].setScrollTop(top);
|
|
39
|
-
}
|
|
40
|
-
finally {
|
|
41
|
-
this.expected[other] = this.editors[other].getScrollTop();
|
|
42
|
-
this.syncing = false;
|
|
43
|
-
}
|
|
39
|
+
this.syncing = true;
|
|
40
|
+
try {
|
|
41
|
+
this.editors[other].setScrollTop(top);
|
|
42
|
+
} finally {
|
|
43
|
+
this.expected[other] = this.editors[other].getScrollTop();
|
|
44
|
+
this.syncing = false;
|
|
44
45
|
}
|
|
45
|
-
}
|
|
46
|
+
}
|
|
47
|
+
}
|
package/dist/symbol-links.js
CHANGED
|
@@ -3,19 +3,19 @@ export const SYMBOL_LINK_CLASS = 'cursor-pointer hover:text-accent hover:underli
|
|
|
3
3
|
const TYPE_NAME = /^[A-Z][A-Za-z0-9_]*$/;
|
|
4
4
|
/* A name that starts with a capital and has a lowercase letter, which leaves `DEFAULT_WEIGHTS` and `T` alone. */
|
|
5
5
|
export function isTypeName(name) {
|
|
6
|
-
|
|
6
|
+
return TYPE_NAME.test(name) && /[a-z]/.test(name);
|
|
7
7
|
}
|
|
8
8
|
/*
|
|
9
9
|
* Marks the type-like names of a highlighted snippet as links. Shiki writes each token as a span of its own,
|
|
10
10
|
* so a name that is the whole text of a token is one; a string or a comment is never that.
|
|
11
11
|
*/
|
|
12
12
|
export function linkTypeNames(html) {
|
|
13
|
-
|
|
13
|
+
return html.replace(/>([A-Z][A-Za-z0-9_]*)</g, (match, name) => isTypeName(name) ? `><span data-symbol="${name}" class="${SYMBOL_LINK_CLASS}">${name}</span><` : match);
|
|
14
14
|
}
|
|
15
15
|
const DECLARES = /\b(?:class|interface|enum|trait|type|namespace|struct|function|const|let|var)\s+&?([A-Za-z_$][\w$]*)/;
|
|
16
16
|
/* The name a signature declares, such as `IssueTicketsMessage` in `final class IssueTicketsMessage implements MessageInterface`; null for one that declares nothing, such as a method of a class. */
|
|
17
17
|
export function declaredNameOf(code) {
|
|
18
|
-
|
|
18
|
+
return DECLARES.exec(code)?.[1] ?? null;
|
|
19
19
|
}
|
|
20
20
|
/* The symbol kinds a type name can mean: module, namespace, class, enum, interface, struct and type parameter. */
|
|
21
21
|
const TYPE_KINDS = new Set([2, 3, 5, 10, 11, 23, 26]);
|
|
@@ -25,26 +25,34 @@ const TYPE_KINDS = new Set([2, 3, 5, 10, 11, 23, 26]);
|
|
|
25
25
|
* namespace) the current file names, which is how a file says which `Message` it means.
|
|
26
26
|
*/
|
|
27
27
|
export function placesOfName(result, name, fileText) {
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
}
|
|
28
|
+
const found = (result ?? []).filter(symbol => symbol.name === name);
|
|
29
|
+
const types = found.filter(symbol => TYPE_KINDS.has(symbol.kind));
|
|
30
|
+
let candidates = types.length > 0 ? types : found;
|
|
31
|
+
if (candidates.length > 1) {
|
|
32
|
+
const named = candidates.filter(symbol => symbol.containerName !== undefined && symbol.containerName !== '' && fileText.includes(symbol.containerName));
|
|
33
|
+
if (named.length > 0) {
|
|
34
|
+
candidates = named;
|
|
36
35
|
}
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
}
|
|
36
|
+
}
|
|
37
|
+
const seen = new Set();
|
|
38
|
+
return candidates.map(symbol => 'range' in symbol.location ? symbol.location : {
|
|
39
|
+
uri: symbol.location.uri,
|
|
40
|
+
range: {
|
|
41
|
+
start: {
|
|
42
|
+
line: 0,
|
|
43
|
+
character: 0
|
|
44
|
+
},
|
|
45
|
+
end: {
|
|
46
|
+
line: 0,
|
|
47
|
+
character: 0
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}).filter(location => {
|
|
51
|
+
const key = `${location.uri}\0${location.range.start.line}`;
|
|
52
|
+
if (seen.has(key)) {
|
|
53
|
+
return false;
|
|
54
|
+
}
|
|
55
|
+
seen.add(key);
|
|
56
|
+
return true;
|
|
57
|
+
});
|
|
58
|
+
}
|
|
@@ -1,152 +1,162 @@
|
|
|
1
1
|
/* The order the groups are listed in: what a file declares, then what those declare. */
|
|
2
|
-
export const SYMBOL_GROUPS = [
|
|
3
|
-
'namespaces',
|
|
4
|
-
'classes',
|
|
5
|
-
'interfaces',
|
|
6
|
-
'enums',
|
|
7
|
-
'functions',
|
|
8
|
-
'methods',
|
|
9
|
-
'properties',
|
|
10
|
-
'variables',
|
|
11
|
-
'constants',
|
|
12
|
-
'other'
|
|
13
|
-
];
|
|
2
|
+
export const SYMBOL_GROUPS = ['namespaces', 'classes', 'interfaces', 'enums', 'functions', 'methods', 'properties', 'variables', 'constants', 'other'];
|
|
14
3
|
const GROUP_OF_KIND = {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
4
|
+
2: 'namespaces',
|
|
5
|
+
3: 'namespaces',
|
|
6
|
+
4: 'namespaces',
|
|
7
|
+
5: 'classes',
|
|
8
|
+
23: 'classes',
|
|
9
|
+
11: 'interfaces',
|
|
10
|
+
10: 'enums',
|
|
11
|
+
22: 'enums',
|
|
12
|
+
12: 'functions',
|
|
13
|
+
6: 'methods',
|
|
14
|
+
9: 'methods',
|
|
15
|
+
7: 'properties',
|
|
16
|
+
8: 'properties',
|
|
17
|
+
13: 'variables',
|
|
18
|
+
14: 'constants',
|
|
19
|
+
26: 'other'
|
|
31
20
|
};
|
|
32
21
|
export function groupOfKind(kind) {
|
|
33
|
-
|
|
22
|
+
return GROUP_OF_KIND[kind] ?? 'other';
|
|
34
23
|
}
|
|
35
24
|
const ENUM_MEMBER = 22;
|
|
36
25
|
const LETTERS = {
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
26
|
+
namespaces: 'N',
|
|
27
|
+
classes: 'C',
|
|
28
|
+
interfaces: 'I',
|
|
29
|
+
enums: 'E',
|
|
30
|
+
functions: 'f',
|
|
31
|
+
methods: 'm',
|
|
32
|
+
properties: 'p',
|
|
33
|
+
variables: 'v',
|
|
34
|
+
constants: 'c',
|
|
35
|
+
other: '·'
|
|
47
36
|
};
|
|
48
37
|
/* The letter in the badge in front of a symbol. */
|
|
49
38
|
export function letterOfKind(kind) {
|
|
50
|
-
|
|
39
|
+
return kind === ENUM_MEMBER ? 'e' : LETTERS[groupOfKind(kind)];
|
|
51
40
|
}
|
|
52
41
|
const TONES = {
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
42
|
+
namespaces: 'other',
|
|
43
|
+
classes: 'type',
|
|
44
|
+
interfaces: 'type',
|
|
45
|
+
enums: 'type',
|
|
46
|
+
functions: 'callable',
|
|
47
|
+
methods: 'callable',
|
|
48
|
+
properties: 'value',
|
|
49
|
+
variables: 'value',
|
|
50
|
+
constants: 'value',
|
|
51
|
+
other: 'other'
|
|
63
52
|
};
|
|
64
53
|
export function toneOfKind(kind) {
|
|
65
|
-
|
|
54
|
+
return TONES[groupOfKind(kind)];
|
|
66
55
|
}
|
|
67
56
|
function isHierarchical(symbols) {
|
|
68
|
-
|
|
57
|
+
return symbols.length > 0 && 'selectionRange' in symbols[0];
|
|
69
58
|
}
|
|
70
59
|
/* The symbols of a file, parents before their children, in the order of the file. */
|
|
71
60
|
export function entriesOf(result) {
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
else {
|
|
89
|
-
for (const symbol of result) {
|
|
90
|
-
add(symbol.name, symbol.kind, symbol.containerName ?? '', '', symbol.location.range.start);
|
|
91
|
-
}
|
|
61
|
+
const entries = [];
|
|
62
|
+
const add = (name, kind, container, detail, at) => {
|
|
63
|
+
entries.push({
|
|
64
|
+
id: String(entries.length),
|
|
65
|
+
name,
|
|
66
|
+
kind,
|
|
67
|
+
container,
|
|
68
|
+
detail,
|
|
69
|
+
line: at.line,
|
|
70
|
+
character: at.character
|
|
71
|
+
});
|
|
72
|
+
};
|
|
73
|
+
const walk = (symbols, container) => {
|
|
74
|
+
for (const symbol of symbols) {
|
|
75
|
+
add(symbol.name, symbol.kind, container, symbol.detail ?? '', symbol.selectionRange.start);
|
|
76
|
+
walk(symbol.children ?? [], container === '' ? symbol.name : `${container}.${symbol.name}`);
|
|
92
77
|
}
|
|
78
|
+
};
|
|
79
|
+
if (result === null || result.length === 0) {
|
|
93
80
|
return entries;
|
|
81
|
+
}
|
|
82
|
+
if (isHierarchical(result)) {
|
|
83
|
+
walk(result, '');
|
|
84
|
+
} else {
|
|
85
|
+
for (const symbol of result) {
|
|
86
|
+
add(symbol.name, symbol.kind, symbol.containerName ?? '', '', symbol.location.range.start);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
return entries;
|
|
94
90
|
}
|
|
95
91
|
/* How well a query matches a name: 3 for a prefix, 2 for a part of it, 1 for its letters in order, 0 for no match. Case is ignored. */
|
|
96
92
|
export function scoreOf(name, query) {
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
return 1;
|
|
101
|
-
}
|
|
102
|
-
if (haystack.startsWith(needle)) {
|
|
103
|
-
return 3;
|
|
104
|
-
}
|
|
105
|
-
if (haystack.includes(needle)) {
|
|
106
|
-
return 2;
|
|
107
|
-
}
|
|
108
|
-
let from = 0;
|
|
109
|
-
for (const character of needle) {
|
|
110
|
-
from = haystack.indexOf(character, from) + 1;
|
|
111
|
-
if (from === 0) {
|
|
112
|
-
return 0;
|
|
113
|
-
}
|
|
114
|
-
}
|
|
93
|
+
const haystack = name.toLowerCase();
|
|
94
|
+
const needle = query.toLowerCase();
|
|
95
|
+
if (needle === '') {
|
|
115
96
|
return 1;
|
|
97
|
+
}
|
|
98
|
+
if (haystack.startsWith(needle)) {
|
|
99
|
+
return 3;
|
|
100
|
+
}
|
|
101
|
+
if (haystack.includes(needle)) {
|
|
102
|
+
return 2;
|
|
103
|
+
}
|
|
104
|
+
let from = 0;
|
|
105
|
+
for (const character of needle) {
|
|
106
|
+
from = haystack.indexOf(character, from) + 1;
|
|
107
|
+
if (from === 0) {
|
|
108
|
+
return 0;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
return 1;
|
|
116
112
|
}
|
|
117
113
|
/* The entries that match, best first within each group; without a query, in the order of the file. */
|
|
118
114
|
export function filterEntries(entries, query) {
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
115
|
+
const trimmed = query.trim();
|
|
116
|
+
const scored = entries.map((entry, index) => ({
|
|
117
|
+
entry,
|
|
118
|
+
index,
|
|
119
|
+
score: scoreOf(entry.name, trimmed)
|
|
120
|
+
})).filter(candidate => candidate.score > 0);
|
|
121
|
+
return scored.sort((left, right) => trimmed === '' ? left.index - right.index : right.score - left.score || left.index - right.index).map(candidate => candidate.entry);
|
|
124
122
|
}
|
|
125
123
|
/* The entries in their groups, in the order of the groups, and so in the order the list is walked with the arrows. */
|
|
126
124
|
export function groupEntries(entries) {
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
125
|
+
return SYMBOL_GROUPS.flatMap(group => {
|
|
126
|
+
const own = entries.filter(entry => groupOfKind(entry.kind) === group);
|
|
127
|
+
return own.length === 0 ? [] : [{
|
|
128
|
+
group,
|
|
129
|
+
entries: own
|
|
130
|
+
}];
|
|
131
|
+
});
|
|
131
132
|
}
|
|
132
133
|
/* `#name` searches the whole project, `:12` goes to a line, anything else filters the symbols of the file. */
|
|
133
134
|
export function modeOf(input) {
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
135
|
+
if (input.startsWith('#')) {
|
|
136
|
+
return {
|
|
137
|
+
mode: 'workspace',
|
|
138
|
+
text: input.slice(1).trim()
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
if (input.startsWith(':')) {
|
|
142
|
+
const line = Number.parseInt(input.slice(1), 10);
|
|
143
|
+
return {
|
|
144
|
+
mode: 'line',
|
|
145
|
+
line: Number.isFinite(line) && line > 0 ? line : null
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
return {
|
|
149
|
+
mode: 'symbol',
|
|
150
|
+
text: input
|
|
151
|
+
};
|
|
142
152
|
}
|
|
143
153
|
export function workspaceEntriesOf(result) {
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
}
|
|
154
|
+
return (result ?? []).map((symbol, index) => ({
|
|
155
|
+
id: String(index),
|
|
156
|
+
name: symbol.name,
|
|
157
|
+
kind: symbol.kind,
|
|
158
|
+
container: symbol.containerName ?? '',
|
|
159
|
+
uri: symbol.location.uri,
|
|
160
|
+
line: 'range' in symbol.location ? symbol.location.range.start.line : 0
|
|
161
|
+
}));
|
|
162
|
+
}
|