code-server/lib/vscode/extensions/npm/src/readScripts.ts
2021-03-11 10:27:10 -07:00

74 lines
2.0 KiB
TypeScript

/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { JSONVisitor, visit } from 'jsonc-parser';
import { Location, Position, Range, TextDocument } from 'vscode';
export interface INpmScriptReference {
name: string;
value: string;
nameRange: Range;
valueRange: Range;
}
export interface INpmScriptInfo {
location: Location;
scripts: INpmScriptReference[];
}
export const readScripts = (document: TextDocument, buffer = document.getText()): INpmScriptInfo | undefined => {
let start: Position | undefined;
let end: Position | undefined;
let inScripts = false;
let buildingScript: { name: string; nameRange: Range } | void;
let level = 0;
const scripts: INpmScriptReference[] = [];
const visitor: JSONVisitor = {
onError() {
// no-op
},
onObjectBegin() {
level++;
},
onObjectEnd(offset) {
if (inScripts) {
end = document.positionAt(offset);
inScripts = false;
}
level--;
},
onLiteralValue(value: unknown, offset: number, length: number) {
if (buildingScript && typeof value === 'string') {
scripts.push({
...buildingScript,
value,
valueRange: new Range(document.positionAt(offset), document.positionAt(offset + length)),
});
buildingScript = undefined;
}
},
onObjectProperty(property: string, offset: number, length: number) {
if (level === 1 && property === 'scripts') {
inScripts = true;
start = document.positionAt(offset);
} else if (inScripts) {
buildingScript = {
name: property,
nameRange: new Range(document.positionAt(offset), document.positionAt(offset + length))
};
}
},
};
visit(buffer, visitor);
if (start === undefined) {
return undefined;
}
return { location: new Location(document.uri, new Range(start, end ?? start)), scripts };
};