Merge pull request #3476 from Microsoft/classificationPerf2
Don't bother trying to semantically classify names that could never be typenames.
This commit is contained in:
commit
a3916ffb50
|
@ -90,10 +90,12 @@ namespace ts {
|
|||
let lastContainer: Node;
|
||||
let symbolCount = 0;
|
||||
let Symbol = objectAllocator.getSymbolConstructor();
|
||||
let classifiableNames: Map<string> = {};
|
||||
|
||||
if (!file.locals) {
|
||||
bind(file);
|
||||
file.symbolCount = symbolCount;
|
||||
file.classifiableNames = classifiableNames;
|
||||
}
|
||||
|
||||
return;
|
||||
|
@ -194,6 +196,11 @@ namespace ts {
|
|||
symbol = hasProperty(symbolTable, name)
|
||||
? symbolTable[name]
|
||||
: (symbolTable[name] = createSymbol(SymbolFlags.None, name));
|
||||
|
||||
if (name && (includes & SymbolFlags.Classifiable)) {
|
||||
classifiableNames[name] = name;
|
||||
}
|
||||
|
||||
if (symbol.flags & excludes) {
|
||||
if (node.name) {
|
||||
node.name.parent = node;
|
||||
|
|
|
@ -148,6 +148,7 @@ namespace ts {
|
|||
let commonSourceDirectory: string;
|
||||
let diagnosticsProducingTypeChecker: TypeChecker;
|
||||
let noDiagnosticsTypeChecker: TypeChecker;
|
||||
let classifiableNames: Map<string>;
|
||||
|
||||
let start = new Date().getTime();
|
||||
|
||||
|
@ -172,6 +173,7 @@ namespace ts {
|
|||
getDeclarationDiagnostics,
|
||||
getCompilerOptionsDiagnostics,
|
||||
getTypeChecker,
|
||||
getClassifiableNames,
|
||||
getDiagnosticsProducingTypeChecker,
|
||||
getCommonSourceDirectory: () => commonSourceDirectory,
|
||||
emit,
|
||||
|
@ -183,6 +185,20 @@ namespace ts {
|
|||
};
|
||||
return program;
|
||||
|
||||
function getClassifiableNames() {
|
||||
if (!classifiableNames) {
|
||||
// Initialize a checker so that all our files are bound.
|
||||
getTypeChecker();
|
||||
classifiableNames = {};
|
||||
|
||||
for (let sourceFile of files) {
|
||||
copyMap(sourceFile.classifiableNames, classifiableNames);
|
||||
}
|
||||
}
|
||||
|
||||
return classifiableNames;
|
||||
}
|
||||
|
||||
function getEmitHost(writeFileCallback?: WriteFileCallback): EmitHost {
|
||||
return {
|
||||
getCanonicalFileName: fileName => host.getCanonicalFileName(fileName),
|
||||
|
|
|
@ -1172,6 +1172,8 @@ namespace ts {
|
|||
// Stores a line map for the file.
|
||||
// This field should never be used directly to obtain line map, use getLineMap function instead.
|
||||
/* @internal */ lineMap: number[];
|
||||
|
||||
/* @internal */ classifiableNames?: Map<string>;
|
||||
}
|
||||
|
||||
export interface ScriptReferenceHost {
|
||||
|
@ -1223,6 +1225,8 @@ namespace ts {
|
|||
// language service).
|
||||
/* @internal */ getDiagnosticsProducingTypeChecker(): TypeChecker;
|
||||
|
||||
/* @internal */ getClassifiableNames(): Map<string>;
|
||||
|
||||
/* @internal */ getNodeCount(): number;
|
||||
/* @internal */ getIdentifierCount(): number;
|
||||
/* @internal */ getSymbolCount(): number;
|
||||
|
@ -1519,6 +1523,11 @@ namespace ts {
|
|||
|
||||
PropertyOrAccessor = Property | Accessor,
|
||||
Export = ExportNamespace | ExportType | ExportValue,
|
||||
|
||||
/* @internal */
|
||||
// The set of things we consider semantically classifiable. Used to speed up the LS during
|
||||
// classification.
|
||||
Classifiable = Class | Enum | TypeAlias | Interface | TypeParameter | Module,
|
||||
}
|
||||
|
||||
export interface Symbol {
|
||||
|
|
|
@ -5992,6 +5992,7 @@ namespace ts {
|
|||
let typeChecker = program.getTypeChecker();
|
||||
|
||||
let result: number[] = [];
|
||||
let classifiableNames = program.getClassifiableNames();
|
||||
processNode(sourceFile);
|
||||
|
||||
return { spans: result, endOfLineState: EndOfLineState.None };
|
||||
|
@ -6004,6 +6005,9 @@ namespace ts {
|
|||
|
||||
function classifySymbol(symbol: Symbol, meaningAtPosition: SemanticMeaning): ClassificationType {
|
||||
let flags = symbol.getFlags();
|
||||
if ((flags & SymbolFlags.Classifiable) === SymbolFlags.None) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (flags & SymbolFlags.Class) {
|
||||
return ClassificationType.className;
|
||||
|
@ -6048,11 +6052,18 @@ namespace ts {
|
|||
// Only walk into nodes that intersect the requested span.
|
||||
if (node && textSpanIntersectsWith(span, node.getFullStart(), node.getFullWidth())) {
|
||||
if (node.kind === SyntaxKind.Identifier && !nodeIsMissing(node)) {
|
||||
let symbol = typeChecker.getSymbolAtLocation(node);
|
||||
if (symbol) {
|
||||
let type = classifySymbol(symbol, getMeaningFromLocation(node));
|
||||
if (type) {
|
||||
pushClassification(node.getStart(), node.getWidth(), type);
|
||||
let identifier = <Identifier>node;
|
||||
|
||||
// Only bother calling into the typechecker if this is an identifier that
|
||||
// could possibly resolve to a type name. This makes classification run
|
||||
// in a third of the time it would normally take.
|
||||
if (classifiableNames[identifier.text]) {
|
||||
let symbol = typeChecker.getSymbolAtLocation(node);
|
||||
if (symbol) {
|
||||
let type = classifySymbol(symbol, getMeaningFromLocation(node));
|
||||
if (type) {
|
||||
pushClassification(node.getStart(), node.getWidth(), type);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue