in src/services/jsonDocumentSymbols.ts [102:192]
public findDocumentSymbols2(document: TextDocument, doc: Parser.JSONDocument, context: DocumentSymbolsContext = { resultLimit: Number.MAX_VALUE }): DocumentSymbol[] {
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: DocumentSymbol[] = [];
for (const item of root.items) {
if (item.type === 'object') {
for (const property of item.properties) {
if (property.keyNode.value === 'key' && property.valueNode) {
const range = getRange(document, item);
const selectionRange = getRange(document, property.keyNode);
result.push({ name: Parser.getNodeValue(property.valueNode), kind: SymbolKind.Function, range, selectionRange });
limit--;
if (limit <= 0) {
if (context && context.onResultLimitExceeded) {
context.onResultLimitExceeded(resourceString);
}
return result;
}
}
}
}
}
return result;
}
}
const result: DocumentSymbol[] = [];
const toVisit: { node: ASTNode, result: DocumentSymbol[] }[] = [
{ node: root, result }
];
let nextToVisit = 0;
let limitExceeded = false;
const collectOutlineEntries = (node: ASTNode, result: DocumentSymbol[]) => {
if (node.type === 'array') {
node.items.forEach((node, index) => {
if (node) {
if (limit > 0) {
limit--;
const range = getRange(document, node);
const selectionRange = range;
const name = String(index);
const symbol = { name, kind: this.getSymbolKind(node.type), range, selectionRange, children: [] };
result.push(symbol);
toVisit.push({ result: symbol.children, node });
} else {
limitExceeded = true;
}
}
});
} else if (node.type === 'object') {
node.properties.forEach((property: PropertyASTNode) => {
const valueNode = property.valueNode;
if (valueNode) {
if (limit > 0) {
limit--;
const range = getRange(document, property);
const selectionRange = getRange(document, property.keyNode);
const children: DocumentSymbol[] = [];
const symbol: DocumentSymbol = { name: this.getKeyLabel(property), kind: this.getSymbolKind(valueNode.type), range, selectionRange, children, detail: this.getDetail(valueNode) };
result.push(symbol);
toVisit.push({ result: children, node: valueNode });
} else {
limitExceeded = true;
}
}
});
}
};
// breath first traversal
while (nextToVisit < toVisit.length) {
const next = toVisit[nextToVisit++];
collectOutlineEntries(next.node, next.result);
}
if (limitExceeded && context && context.onResultLimitExceeded) {
context.onResultLimitExceeded(resourceString);
}
return result;
}