Skip to content

Commit b0f291b

Browse files
Merge branch 'master' into cancellableClassification
Conflicts: src/services/services.ts
2 parents 053be42 + ae17c61 commit b0f291b

File tree

13 files changed

+198
-94
lines changed

13 files changed

+198
-94
lines changed

src/compiler/checker.ts

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,14 @@ namespace ts {
159159
}
160160
};
161161

162+
let subtypeRelation: Map<RelationComparisonResult> = {};
163+
let assignableRelation: Map<RelationComparisonResult> = {};
164+
let identityRelation: Map<RelationComparisonResult> = {};
165+
166+
initializeTypeChecker();
167+
168+
return checker;
169+
162170
function getEmitResolver(sourceFile?: SourceFile) {
163171
// Ensure we have all the type information in place for this file so that all the
164172
// emitter questions of this resolver will return the right information.
@@ -4221,10 +4229,6 @@ namespace ts {
42214229

42224230
// TYPE CHECKING
42234231

4224-
let subtypeRelation: Map<RelationComparisonResult> = {};
4225-
let assignableRelation: Map<RelationComparisonResult> = {};
4226-
let identityRelation: Map<RelationComparisonResult> = {};
4227-
42284232
function isTypeIdenticalTo(source: Type, target: Type): boolean {
42294233
return checkTypeRelatedTo(source, target, identityRelation, /*errorNode*/ undefined);
42304234
}
@@ -5761,6 +5765,7 @@ namespace ts {
57615765
let signature = getResolvedSignature(expr);
57625766

57635767
if (signature.typePredicate &&
5768+
expr.arguments[signature.typePredicate.parameterIndex] &&
57645769
getSymbolAtLocation(expr.arguments[signature.typePredicate.parameterIndex]) === symbol) {
57655770

57665771
if (!assumeTrue) {
@@ -13614,9 +13619,5 @@ namespace ts {
1361413619
return true;
1361513620
}
1361613621
}
13617-
13618-
initializeTypeChecker();
13619-
13620-
return checker;
1362113622
}
1362213623
}

src/compiler/parser.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1491,12 +1491,20 @@ namespace ts {
14911491
switch (node.kind) {
14921492
case SyntaxKind.Constructor:
14931493
case SyntaxKind.IndexSignature:
1494-
case SyntaxKind.MethodDeclaration:
14951494
case SyntaxKind.GetAccessor:
14961495
case SyntaxKind.SetAccessor:
14971496
case SyntaxKind.PropertyDeclaration:
14981497
case SyntaxKind.SemicolonClassElement:
14991498
return true;
1499+
case SyntaxKind.MethodDeclaration:
1500+
// Method declarations are not necessarily reusable. An object-literal
1501+
// may have a method calls "constructor(...)" and we must reparse that
1502+
// into an actual .ConstructorDeclaration.
1503+
let methodDeclaration = <MethodDeclaration>node;
1504+
let nameIsConstructor = methodDeclaration.name.kind === SyntaxKind.Identifier &&
1505+
(<Identifier>methodDeclaration.name).originalKeywordKind === SyntaxKind.ConstructorKeyword;
1506+
1507+
return !nameIsConstructor;
15001508
}
15011509
}
15021510

src/compiler/program.ts

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,10 @@ namespace ts {
105105
}
106106

107107
export function getPreEmitDiagnostics(program: Program, sourceFile?: SourceFile): Diagnostic[] {
108-
let diagnostics = program.getSyntacticDiagnostics(sourceFile).concat(program.getGlobalDiagnostics()).concat(program.getSemanticDiagnostics(sourceFile));
108+
let diagnostics = program.getOptionsDiagnostics().concat(
109+
program.getSyntacticDiagnostics(sourceFile),
110+
program.getGlobalDiagnostics(),
111+
program.getSemanticDiagnostics(sourceFile));
109112

110113
if (program.getCompilerOptions().declaration) {
111114
diagnostics.concat(program.getDeclarationDiagnostics(sourceFile));
@@ -177,10 +180,10 @@ namespace ts {
177180
getSourceFiles: () => files,
178181
getCompilerOptions: () => options,
179182
getSyntacticDiagnostics,
183+
getOptionsDiagnostics,
180184
getGlobalDiagnostics,
181185
getSemanticDiagnostics,
182186
getDeclarationDiagnostics,
183-
getCompilerOptionsDiagnostics,
184187
getTypeChecker,
185188
getClassifiableNames,
186189
getDiagnosticsProducingTypeChecker,
@@ -311,19 +314,15 @@ namespace ts {
311314
}
312315
}
313316

314-
function getCompilerOptionsDiagnostics(): Diagnostic[] {
317+
function getOptionsDiagnostics(): Diagnostic[] {
315318
let allDiagnostics: Diagnostic[] = [];
316319
addRange(allDiagnostics, diagnostics.getGlobalDiagnostics());
317320
return sortAndDeduplicateDiagnostics(allDiagnostics);
318321
}
319322

320323
function getGlobalDiagnostics(): Diagnostic[] {
321-
let typeChecker = getDiagnosticsProducingTypeChecker();
322-
323324
let allDiagnostics: Diagnostic[] = [];
324-
addRange(allDiagnostics, typeChecker.getGlobalDiagnostics());
325-
addRange(allDiagnostics, diagnostics.getGlobalDiagnostics());
326-
325+
addRange(allDiagnostics, getDiagnosticsProducingTypeChecker().getGlobalDiagnostics());
327326
return sortAndDeduplicateDiagnostics(allDiagnostics);
328327
}
329328

src/compiler/scanner.ts

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -376,8 +376,31 @@ namespace ts {
376376
return ch >= CharacterCodes._0 && ch <= CharacterCodes._7;
377377
}
378378

379+
export function couldStartTrivia(text: string, pos: number): boolean {
380+
// Keep in sync with skipTrivia
381+
let ch = text.charCodeAt(pos);
382+
switch (ch) {
383+
case CharacterCodes.carriageReturn:
384+
case CharacterCodes.lineFeed:
385+
case CharacterCodes.tab:
386+
case CharacterCodes.verticalTab:
387+
case CharacterCodes.formFeed:
388+
case CharacterCodes.space:
389+
case CharacterCodes.slash:
390+
// starts of normal trivia
391+
case CharacterCodes.lessThan:
392+
case CharacterCodes.equals:
393+
case CharacterCodes.greaterThan:
394+
// Starts of conflict marker trivia
395+
return true;
396+
default:
397+
return ch > CharacterCodes.maxAsciiCharacter;
398+
}
399+
}
400+
379401
/* @internal */
380402
export function skipTrivia(text: string, pos: number, stopAfterLineBreak?: boolean): number {
403+
// Keep in sync with couldStartTrivia
381404
while (true) {
382405
let ch = text.charCodeAt(pos);
383406
switch (ch) {

src/compiler/types.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1212,11 +1212,11 @@ namespace ts {
12121212
*/
12131213
emit(targetSourceFile?: SourceFile, writeFile?: WriteFileCallback): EmitResult;
12141214

1215-
getSyntacticDiagnostics(sourceFile?: SourceFile): Diagnostic[];
1215+
getOptionsDiagnostics(): Diagnostic[];
12161216
getGlobalDiagnostics(): Diagnostic[];
1217+
getSyntacticDiagnostics(sourceFile?: SourceFile): Diagnostic[];
12171218
getSemanticDiagnostics(sourceFile?: SourceFile): Diagnostic[];
12181219
getDeclarationDiagnostics(sourceFile?: SourceFile): Diagnostic[];
1219-
/* @internal */ getCompilerOptionsDiagnostics(): Diagnostic[];
12201220

12211221
/**
12221222
* Gets a type checker that can be used to semantically analyze source fils in the program.

src/compiler/utilities.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2090,6 +2090,12 @@ namespace ts {
20902090
return start <= textSpanEnd(span) && end >= span.start;
20912091
}
20922092

2093+
export function decodedTextSpanIntersectsWith(start1: number, length1: number, start2: number, length2: number) {
2094+
let end1 = start1 + length1;
2095+
let end2 = start2 + length2;
2096+
return start2 <= end1 && end2 >= start1;
2097+
}
2098+
20932099
export function textSpanIntersectsWithPosition(span: TextSpan, position: number) {
20942100
return position <= textSpanEnd(span) && position >= span.start;
20952101
}

src/services/services.ts

Lines changed: 52 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,7 @@ namespace ts {
167167
}
168168

169169
public getFullWidth(): number {
170-
return this.end - this.getFullStart();
170+
return this.end - this.pos;
171171
}
172172

173173
public getLeadingTriviaWidth(sourceFile?: SourceFile): number {
@@ -973,6 +973,9 @@ namespace ts {
973973

974974
getSyntacticDiagnostics(fileName: string): Diagnostic[];
975975
getSemanticDiagnostics(fileName: string): Diagnostic[];
976+
977+
// TODO: Rename this to getProgramDiagnostics to better indicate that these are any
978+
// diagnostics present for the program level, and not just 'options' diagnostics.
976979
getCompilerOptionsDiagnostics(): Diagnostic[];
977980

978981
/**
@@ -1789,11 +1792,6 @@ namespace ts {
17891792
sourceFile.moduleName = moduleName;
17901793
}
17911794

1792-
// Store syntactic diagnostics
1793-
if (diagnostics && sourceFile.parseDiagnostics) {
1794-
diagnostics.push(...sourceFile.parseDiagnostics);
1795-
}
1796-
17971795
let newLine = getNewLineCharacter(options);
17981796

17991797
// Output
@@ -1815,9 +1813,8 @@ namespace ts {
18151813

18161814
var program = createProgram([inputFileName], options, compilerHost);
18171815

1818-
if (diagnostics) {
1819-
diagnostics.push(...program.getCompilerOptionsDiagnostics());
1820-
}
1816+
addRange(/*to*/ diagnostics, /*from*/ program.getSyntacticDiagnostics(sourceFile));
1817+
addRange(/*to*/ diagnostics, /*from*/ program.getOptionsDiagnostics());
18211818

18221819
// Emit
18231820
program.emit();
@@ -2796,7 +2793,7 @@ namespace ts {
27962793

27972794
function getCompilerOptionsDiagnostics() {
27982795
synchronizeHostData();
2799-
return program.getGlobalDiagnostics();
2796+
return program.getOptionsDiagnostics().concat(program.getGlobalDiagnostics());
28002797
}
28012798

28022799
/// Completion
@@ -4188,7 +4185,7 @@ namespace ts {
41884185
var result: DefinitionInfo[] = [];
41894186
forEach((<UnionType>type).types, t => {
41904187
if (t.symbol) {
4191-
result.push(...getDefinitionFromSymbol(t.symbol, node));
4188+
addRange(/*to*/ result, /*from*/ getDefinitionFromSymbol(t.symbol, node));
41924189
}
41934190
});
41944191
return result;
@@ -6141,6 +6138,8 @@ namespace ts {
61416138
function getEncodedSyntacticClassifications(fileName: string, span: TextSpan): Classifications {
61426139
// doesn't use compiler - no need to synchronize with host
61436140
let sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName);
6141+
let spanStart = span.start;
6142+
let spanLength = span.length;
61446143

61456144
// Make a scanner we can get trivia from.
61466145
let triviaScanner = createScanner(ScriptTarget.Latest, /*skipTrivia:*/ false, sourceFile.text);
@@ -6157,48 +6156,55 @@ namespace ts {
61576156
result.push(type);
61586157
}
61596158

6160-
function classifyLeadingTrivia(token: Node): void {
6161-
let tokenStart = skipTrivia(sourceFile.text, token.pos, /*stopAfterLineBreak:*/ false);
6162-
if (tokenStart === token.pos) {
6163-
return;
6164-
}
6165-
6166-
// token has trivia. Classify them appropriately.
6159+
function classifyLeadingTriviaAndGetTokenStart(token: Node): number {
61676160
triviaScanner.setTextPos(token.pos);
61686161
while (true) {
61696162
let start = triviaScanner.getTextPos();
6163+
// only bother scanning if we have something that could be trivia.
6164+
if (!couldStartTrivia(sourceFile.text, start)) {
6165+
return start;
6166+
}
6167+
61706168
let kind = triviaScanner.scan();
61716169
let end = triviaScanner.getTextPos();
61726170
let width = end - start;
61736171

61746172
// The moment we get something that isn't trivia, then stop processing.
61756173
if (!isTrivia(kind)) {
6176-
return;
6174+
return start;
61776175
}
61786176

6179-
// Only bother with the trivia if it at least intersects the span of interest.
6180-
if (textSpanIntersectsWith(span, start, width)) {
6181-
if (isComment(kind)) {
6182-
classifyComment(token, kind, start, width);
6183-
continue;
6184-
}
6177+
// Don't bother with newlines/whitespace.
6178+
if (kind === SyntaxKind.NewLineTrivia || kind === SyntaxKind.WhitespaceTrivia) {
6179+
continue;
6180+
}
61856181

6186-
if (kind === SyntaxKind.ConflictMarkerTrivia) {
6187-
let text = sourceFile.text;
6188-
let ch = text.charCodeAt(start);
6182+
// Only bother with the trivia if it at least intersects the span of interest.
6183+
if (isComment(kind)) {
6184+
classifyComment(token, kind, start, width);
6185+
6186+
// Classifying a comment might cause us to reuse the trivia scanner
6187+
// (because of jsdoc comments). So after we classify the comment make
6188+
// sure we set the scanner position back to where it needs to be.
6189+
triviaScanner.setTextPos(end);
6190+
continue;
6191+
}
61896192

6190-
// for the <<<<<<< and >>>>>>> markers, we just add them in as comments
6191-
// in the classification stream.
6192-
if (ch === CharacterCodes.lessThan || ch === CharacterCodes.greaterThan) {
6193-
pushClassification(start, width, ClassificationType.comment);
6194-
continue;
6195-
}
6193+
if (kind === SyntaxKind.ConflictMarkerTrivia) {
6194+
let text = sourceFile.text;
6195+
let ch = text.charCodeAt(start);
61966196

6197-
// for the ======== add a comment for the first line, and then lex all
6198-
// subsequent lines up until the end of the conflict marker.
6199-
Debug.assert(ch === CharacterCodes.equals);
6200-
classifyDisabledMergeCode(text, start, end);
6197+
// for the <<<<<<< and >>>>>>> markers, we just add them in as comments
6198+
// in the classification stream.
6199+
if (ch === CharacterCodes.lessThan || ch === CharacterCodes.greaterThan) {
6200+
pushClassification(start, width, ClassificationType.comment);
6201+
continue;
62016202
}
6203+
6204+
// for the ======== add a comment for the first line, and then lex all
6205+
// subsequent lines up until the end of the conflict marker.
6206+
Debug.assert(ch === CharacterCodes.equals);
6207+
classifyDisabledMergeCode(text, start, end);
62026208
}
62036209
}
62046210
}
@@ -6317,12 +6323,14 @@ namespace ts {
63176323
}
63186324

63196325
function classifyToken(token: Node): void {
6320-
classifyLeadingTrivia(token);
6326+
let tokenStart = classifyLeadingTriviaAndGetTokenStart(token);
63216327

6322-
if (token.getWidth() > 0) {
6328+
let tokenWidth = token.end - tokenStart;
6329+
Debug.assert(tokenWidth >= 0);
6330+
if (tokenWidth > 0) {
63236331
let type = classifyTokenType(token.kind, token);
63246332
if (type) {
6325-
pushClassification(token.getStart(), token.getWidth(), type);
6333+
pushClassification(tokenStart, tokenWidth, type);
63266334
}
63276335
}
63286336
}
@@ -6427,11 +6435,12 @@ namespace ts {
64276435
}
64286436

64296437
// Ignore nodes that don't intersect the original span to classify.
6430-
if (textSpanIntersectsWith(span, element.getFullStart(), element.getFullWidth())) {
6438+
if (decodedTextSpanIntersectsWith(spanStart, spanLength, element.pos, element.getFullWidth())) {
64316439
checkForClassificationCancellation(element.kind);
64326440

64336441
let children = element.getChildren(sourceFile);
6434-
for (let child of children) {
6442+
for (let i = 0, n = children.length; i < n; i++) {
6443+
let child = children[i];
64356444
if (isToken(child)) {
64366445
classifyToken(child);
64376446
}

0 commit comments

Comments
 (0)