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:
CyrusNajmabadi 2015-06-12 13:14:08 -07:00
commit a3916ffb50
4 changed files with 48 additions and 5 deletions

View file

@ -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;

View file

@ -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),

View file

@ -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 {

View file

@ -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);
}
}
}
}