in src/services/jsonDocumentSymbols.ts [22:100]
public findDocumentSymbols(document: TextDocument, doc: Parser.JSONDocument, context: DocumentSymbolsContext = { resultLimit: Number.MAX_VALUE }): SymbolInformation[] {
const root = doc.root;
if (!root) {
return [];
}
let limit = context.resultLimit || Number.MAX_VALUE;
// special handling for key bindings
const resourceString = document.uri;
if ((resourceString === 'vscode://defaultsettings/keybindings.json') || Strings.endsWith(resourceString.toLowerCase(), '/user/keybindings.json')) {
if (root.type === 'array') {
const result: SymbolInformation[] = [];
for (const item of root.items) {
if (item.type === 'object') {
for (const property of item.properties) {
if (property.keyNode.value === 'key' && property.valueNode) {
const location = Location.create(document.uri, getRange(document, item));
result.push({ name: Parser.getNodeValue(property.valueNode), kind: SymbolKind.Function, location: location });
limit--;
if (limit <= 0) {
if (context && context.onResultLimitExceeded) {
context.onResultLimitExceeded(resourceString);
}
return result;
}
}
}
}
}
return result;
}
}
const toVisit: { node: ASTNode, containerName: string }[] = [
{ node: root, containerName: '' }
];
let nextToVisit = 0;
let limitExceeded = false;
const result: SymbolInformation[] = [];
const collectOutlineEntries = (node: ASTNode, containerName: string): void => {
if (node.type === 'array') {
node.items.forEach(node => {
if (node) {
toVisit.push({ node, containerName });
}
});
} else if (node.type === 'object') {
node.properties.forEach((property: PropertyASTNode) => {
const valueNode = property.valueNode;
if (valueNode) {
if (limit > 0) {
limit--;
const location = Location.create(document.uri, getRange(document, property));
const childContainerName = containerName ? containerName + '.' + property.keyNode.value : property.keyNode.value;
result.push({ name: this.getKeyLabel(property), kind: this.getSymbolKind(valueNode.type), location: location, containerName: containerName });
toVisit.push({ node: valueNode, containerName: childContainerName });
} else {
limitExceeded = true;
}
}
});
}
};
// breath first traversal
while (nextToVisit < toVisit.length) {
const next = toVisit[nextToVisit++];
collectOutlineEntries(next.node, next.containerName);
}
if (limitExceeded && context && context.onResultLimitExceeded) {
context.onResultLimitExceeded(resourceString);
}
return result;
}