Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/extensions/copilot/src/platform/parser/node/selectionParsing.ts
13401 views
1
/*---------------------------------------------------------------------------------------------
2
* Copyright (c) Microsoft Corporation. All rights reserved.
3
* Licensed under the MIT License. See License.txt in the project root for license information.
4
*--------------------------------------------------------------------------------------------*/
5
6
import { SyntaxNode, Tree } from 'web-tree-sitter';
7
import { max } from '../../../util/common/arrays';
8
import { TreeSitterOffsetRange } from './nodes';
9
import { WASMLanguage } from './treeSitterLanguages';
10
import { isDocumentableNode } from './util';
11
12
/**
13
* This function is used to find the most relevant node to document in a parse tree.
14
* It traverses the parse tree and keeps track of documentable nodes that could be used to generate documentation.
15
* The relevance of a node is determined by its intersection with a given range (containerRange).
16
* The function rewards nodes for which the overlap size constitutes a large part of the node and penalizes nodes for non-overlapping range.
17
*
18
* @remarks Exported for testing purposes only.
19
*
20
* @param parseTree - The parse tree to search for the most relevant node.
21
* @param containerRange - The range to intersect with the nodes of the parse tree.
22
* @param language - The language identifier used to determine if a node is documentable.
23
* @returns The most relevant node to document or undefined if no such node is found.
24
*/
25
export function _getNodeMatchingSelection(parseTree: Tree, containerRange: TreeSitterOffsetRange, language: WASMLanguage, match: (node: SyntaxNode, language: WASMLanguage) => RegExpMatchArray | null = isDocumentableNode): SyntaxNode | undefined {
26
27
// nodes to explore
28
let frontier = [parseTree.rootNode];
29
30
// keeps documentable nodes that could be used to generate documentation for
31
const documentableNodes: [SyntaxNode, /* weight (higher better) */ number][] = [];
32
33
while (true) {
34
// nodes that intersect with `containerRange`
35
const candidates = frontier
36
.map((node): [SyntaxNode, number] => [node, TreeSitterOffsetRange.intersectionSize(node, containerRange)])
37
.filter(([_, s]) => s > 0)
38
.sort(([_, s0], [__, s1]) => s1 - s0);
39
40
if (candidates.length === 0) {
41
return documentableNodes.length === 0
42
? undefined
43
: max(documentableNodes, ([_, s0], [__, s1]) => s0 - s1)![0];
44
} else {
45
const reweighedCandidates = candidates
46
.map(([n, overlapSize]): [SyntaxNode, number] => {
47
const nLen = TreeSitterOffsetRange.len(n);
48
const nonOverlappingSize = Math.abs(TreeSitterOffsetRange.len(containerRange) - overlapSize);
49
// reward overlap size but penalize for non-overlapping range
50
const penalizedWeigth = overlapSize - nonOverlappingSize;
51
const normalizedPenalizedWeight = penalizedWeigth / nLen;
52
return [n, normalizedPenalizedWeight];
53
});
54
55
documentableNodes.push(...reweighedCandidates.filter(([node, _]) => match(node, language)));
56
57
frontier = [];
58
frontier.push(...reweighedCandidates.flatMap(([n, s]) => n.children));
59
}
60
}
61
}
62
63