diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index efc3e32166e..4cebc167d59 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -159,6 +159,14 @@ namespace ts { } }; + let subtypeRelation: Map = {}; + let assignableRelation: Map = {}; + let identityRelation: Map = {}; + + initializeTypeChecker(); + + return checker; + function getEmitResolver(sourceFile?: SourceFile) { // Ensure we have all the type information in place for this file so that all the // emitter questions of this resolver will return the right information. @@ -4221,10 +4229,6 @@ namespace ts { // TYPE CHECKING - let subtypeRelation: Map = {}; - let assignableRelation: Map = {}; - let identityRelation: Map = {}; - function isTypeIdenticalTo(source: Type, target: Type): boolean { return checkTypeRelatedTo(source, target, identityRelation, /*errorNode*/ undefined); } @@ -5761,6 +5765,7 @@ namespace ts { let signature = getResolvedSignature(expr); if (signature.typePredicate && + expr.arguments[signature.typePredicate.parameterIndex] && getSymbolAtLocation(expr.arguments[signature.typePredicate.parameterIndex]) === symbol) { if (!assumeTrue) { @@ -13614,9 +13619,5 @@ namespace ts { return true; } } - - initializeTypeChecker(); - - return checker; } } diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index a507125d4bb..a94341dd9c4 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -1491,12 +1491,20 @@ namespace ts { switch (node.kind) { case SyntaxKind.Constructor: case SyntaxKind.IndexSignature: - case SyntaxKind.MethodDeclaration: case SyntaxKind.GetAccessor: case SyntaxKind.SetAccessor: case SyntaxKind.PropertyDeclaration: case SyntaxKind.SemicolonClassElement: return true; + case SyntaxKind.MethodDeclaration: + // Method declarations are not necessarily reusable. An object-literal + // may have a method calls "constructor(...)" and we must reparse that + // into an actual .ConstructorDeclaration. + let methodDeclaration = node; + let nameIsConstructor = methodDeclaration.name.kind === SyntaxKind.Identifier && + (methodDeclaration.name).originalKeywordKind === SyntaxKind.ConstructorKeyword; + + return !nameIsConstructor; } } diff --git a/src/compiler/program.ts b/src/compiler/program.ts index 800e2238a54..2af9ad9987d 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -105,7 +105,10 @@ namespace ts { } export function getPreEmitDiagnostics(program: Program, sourceFile?: SourceFile): Diagnostic[] { - let diagnostics = program.getSyntacticDiagnostics(sourceFile).concat(program.getGlobalDiagnostics()).concat(program.getSemanticDiagnostics(sourceFile)); + let diagnostics = program.getOptionsDiagnostics().concat( + program.getSyntacticDiagnostics(sourceFile), + program.getGlobalDiagnostics(), + program.getSemanticDiagnostics(sourceFile)); if (program.getCompilerOptions().declaration) { diagnostics.concat(program.getDeclarationDiagnostics(sourceFile)); @@ -177,10 +180,10 @@ namespace ts { getSourceFiles: () => files, getCompilerOptions: () => options, getSyntacticDiagnostics, + getOptionsDiagnostics, getGlobalDiagnostics, getSemanticDiagnostics, getDeclarationDiagnostics, - getCompilerOptionsDiagnostics, getTypeChecker, getClassifiableNames, getDiagnosticsProducingTypeChecker, @@ -311,19 +314,15 @@ namespace ts { } } - function getCompilerOptionsDiagnostics(): Diagnostic[] { + function getOptionsDiagnostics(): Diagnostic[] { let allDiagnostics: Diagnostic[] = []; addRange(allDiagnostics, diagnostics.getGlobalDiagnostics()); return sortAndDeduplicateDiagnostics(allDiagnostics); } function getGlobalDiagnostics(): Diagnostic[] { - let typeChecker = getDiagnosticsProducingTypeChecker(); - let allDiagnostics: Diagnostic[] = []; - addRange(allDiagnostics, typeChecker.getGlobalDiagnostics()); - addRange(allDiagnostics, diagnostics.getGlobalDiagnostics()); - + addRange(allDiagnostics, getDiagnosticsProducingTypeChecker().getGlobalDiagnostics()); return sortAndDeduplicateDiagnostics(allDiagnostics); } diff --git a/src/compiler/scanner.ts b/src/compiler/scanner.ts index 39ea940433c..bcc31c39002 100644 --- a/src/compiler/scanner.ts +++ b/src/compiler/scanner.ts @@ -376,8 +376,31 @@ namespace ts { return ch >= CharacterCodes._0 && ch <= CharacterCodes._7; } + export function couldStartTrivia(text: string, pos: number): boolean { + // Keep in sync with skipTrivia + let ch = text.charCodeAt(pos); + switch (ch) { + case CharacterCodes.carriageReturn: + case CharacterCodes.lineFeed: + case CharacterCodes.tab: + case CharacterCodes.verticalTab: + case CharacterCodes.formFeed: + case CharacterCodes.space: + case CharacterCodes.slash: + // starts of normal trivia + case CharacterCodes.lessThan: + case CharacterCodes.equals: + case CharacterCodes.greaterThan: + // Starts of conflict marker trivia + return true; + default: + return ch > CharacterCodes.maxAsciiCharacter; + } + } + /* @internal */ export function skipTrivia(text: string, pos: number, stopAfterLineBreak?: boolean): number { + // Keep in sync with couldStartTrivia while (true) { let ch = text.charCodeAt(pos); switch (ch) { diff --git a/src/compiler/types.ts b/src/compiler/types.ts index c39426a2e22..f9a2fa3b7b4 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -1212,11 +1212,11 @@ namespace ts { */ emit(targetSourceFile?: SourceFile, writeFile?: WriteFileCallback): EmitResult; - getSyntacticDiagnostics(sourceFile?: SourceFile): Diagnostic[]; + getOptionsDiagnostics(): Diagnostic[]; getGlobalDiagnostics(): Diagnostic[]; + getSyntacticDiagnostics(sourceFile?: SourceFile): Diagnostic[]; getSemanticDiagnostics(sourceFile?: SourceFile): Diagnostic[]; getDeclarationDiagnostics(sourceFile?: SourceFile): Diagnostic[]; - /* @internal */ getCompilerOptionsDiagnostics(): Diagnostic[]; /** * Gets a type checker that can be used to semantically analyze source fils in the program. diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index e0fc5fc0269..ee75454ad93 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -2090,6 +2090,12 @@ namespace ts { return start <= textSpanEnd(span) && end >= span.start; } + export function decodedTextSpanIntersectsWith(start1: number, length1: number, start2: number, length2: number) { + let end1 = start1 + length1; + let end2 = start2 + length2; + return start2 <= end1 && end2 >= start1; + } + export function textSpanIntersectsWithPosition(span: TextSpan, position: number) { return position <= textSpanEnd(span) && position >= span.start; } diff --git a/src/services/services.ts b/src/services/services.ts index 188e711ed9f..9940db2c153 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -167,7 +167,7 @@ namespace ts { } public getFullWidth(): number { - return this.end - this.getFullStart(); + return this.end - this.pos; } public getLeadingTriviaWidth(sourceFile?: SourceFile): number { @@ -973,6 +973,9 @@ namespace ts { getSyntacticDiagnostics(fileName: string): Diagnostic[]; getSemanticDiagnostics(fileName: string): Diagnostic[]; + + // TODO: Rename this to getProgramDiagnostics to better indicate that these are any + // diagnostics present for the program level, and not just 'options' diagnostics. getCompilerOptionsDiagnostics(): Diagnostic[]; /** @@ -1789,11 +1792,6 @@ namespace ts { sourceFile.moduleName = moduleName; } - // Store syntactic diagnostics - if (diagnostics && sourceFile.parseDiagnostics) { - diagnostics.push(...sourceFile.parseDiagnostics); - } - let newLine = getNewLineCharacter(options); // Output @@ -1815,9 +1813,8 @@ namespace ts { var program = createProgram([inputFileName], options, compilerHost); - if (diagnostics) { - diagnostics.push(...program.getCompilerOptionsDiagnostics()); - } + addRange(/*to*/ diagnostics, /*from*/ program.getSyntacticDiagnostics(sourceFile)); + addRange(/*to*/ diagnostics, /*from*/ program.getOptionsDiagnostics()); // Emit program.emit(); @@ -2796,7 +2793,7 @@ namespace ts { function getCompilerOptionsDiagnostics() { synchronizeHostData(); - return program.getGlobalDiagnostics(); + return program.getOptionsDiagnostics().concat(program.getGlobalDiagnostics()); } /// Completion @@ -4188,7 +4185,7 @@ namespace ts { var result: DefinitionInfo[] = []; forEach((type).types, t => { if (t.symbol) { - result.push(...getDefinitionFromSymbol(t.symbol, node)); + addRange(/*to*/ result, /*from*/ getDefinitionFromSymbol(t.symbol, node)); } }); return result; @@ -6141,6 +6138,8 @@ namespace ts { function getEncodedSyntacticClassifications(fileName: string, span: TextSpan): Classifications { // doesn't use compiler - no need to synchronize with host let sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); + let spanStart = span.start; + let spanLength = span.length; // Make a scanner we can get trivia from. let triviaScanner = createScanner(ScriptTarget.Latest, /*skipTrivia:*/ false, sourceFile.text); @@ -6157,48 +6156,55 @@ namespace ts { result.push(type); } - function classifyLeadingTrivia(token: Node): void { - let tokenStart = skipTrivia(sourceFile.text, token.pos, /*stopAfterLineBreak:*/ false); - if (tokenStart === token.pos) { - return; - } - - // token has trivia. Classify them appropriately. + function classifyLeadingTriviaAndGetTokenStart(token: Node): number { triviaScanner.setTextPos(token.pos); while (true) { let start = triviaScanner.getTextPos(); + // only bother scanning if we have something that could be trivia. + if (!couldStartTrivia(sourceFile.text, start)) { + return start; + } + let kind = triviaScanner.scan(); let end = triviaScanner.getTextPos(); let width = end - start; // The moment we get something that isn't trivia, then stop processing. if (!isTrivia(kind)) { - return; + return start; + } + + // Don't bother with newlines/whitespace. + if (kind === SyntaxKind.NewLineTrivia || kind === SyntaxKind.WhitespaceTrivia) { + continue; } // Only bother with the trivia if it at least intersects the span of interest. - if (textSpanIntersectsWith(span, start, width)) { - if (isComment(kind)) { - classifyComment(token, kind, start, width); + if (isComment(kind)) { + classifyComment(token, kind, start, width); + + // Classifying a comment might cause us to reuse the trivia scanner + // (because of jsdoc comments). So after we classify the comment make + // sure we set the scanner position back to where it needs to be. + triviaScanner.setTextPos(end); + continue; + } + + if (kind === SyntaxKind.ConflictMarkerTrivia) { + let text = sourceFile.text; + let ch = text.charCodeAt(start); + + // for the <<<<<<< and >>>>>>> markers, we just add them in as comments + // in the classification stream. + if (ch === CharacterCodes.lessThan || ch === CharacterCodes.greaterThan) { + pushClassification(start, width, ClassificationType.comment); continue; } - if (kind === SyntaxKind.ConflictMarkerTrivia) { - let text = sourceFile.text; - let ch = text.charCodeAt(start); - - // for the <<<<<<< and >>>>>>> markers, we just add them in as comments - // in the classification stream. - if (ch === CharacterCodes.lessThan || ch === CharacterCodes.greaterThan) { - pushClassification(start, width, ClassificationType.comment); - continue; - } - - // for the ======== add a comment for the first line, and then lex all - // subsequent lines up until the end of the conflict marker. - Debug.assert(ch === CharacterCodes.equals); - classifyDisabledMergeCode(text, start, end); - } + // for the ======== add a comment for the first line, and then lex all + // subsequent lines up until the end of the conflict marker. + Debug.assert(ch === CharacterCodes.equals); + classifyDisabledMergeCode(text, start, end); } } } @@ -6317,12 +6323,14 @@ namespace ts { } function classifyToken(token: Node): void { - classifyLeadingTrivia(token); + let tokenStart = classifyLeadingTriviaAndGetTokenStart(token); - if (token.getWidth() > 0) { + let tokenWidth = token.end - tokenStart; + Debug.assert(tokenWidth >= 0); + if (tokenWidth > 0) { let type = classifyTokenType(token.kind, token); if (type) { - pushClassification(token.getStart(), token.getWidth(), type); + pushClassification(tokenStart, tokenWidth, type); } } } @@ -6427,11 +6435,12 @@ namespace ts { } // Ignore nodes that don't intersect the original span to classify. - if (textSpanIntersectsWith(span, element.getFullStart(), element.getFullWidth())) { + if (decodedTextSpanIntersectsWith(spanStart, spanLength, element.pos, element.getFullWidth())) { checkForClassificationCancellation(element.kind); let children = element.getChildren(sourceFile); - for (let child of children) { + for (let i = 0, n = children.length; i < n; i++) { + let child = children[i]; if (isToken(child)) { classifyToken(child); } diff --git a/tests/baselines/reference/typeGuardFunctionErrors.errors.txt b/tests/baselines/reference/typeGuardFunctionErrors.errors.txt index 1542bbe0fee..499a51035f2 100644 --- a/tests/baselines/reference/typeGuardFunctionErrors.errors.txt +++ b/tests/baselines/reference/typeGuardFunctionErrors.errors.txt @@ -1,42 +1,43 @@ tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(15,12): error TS2322: Type 'string' is not assignable to type 'boolean'. tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(22,33): error TS2304: Cannot find name 'x'. -tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(26,10): error TS2391: Function implementation is missing or not immediately following the declaration. -tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(27,5): error TS1131: Property or signature expected. -tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(28,1): error TS1128: Declaration or statement expected. -tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(30,38): error TS1225: Cannot find parameter 'x'. -tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(34,51): error TS2322: Type 'B' is not assignable to type 'A'. +tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(26,33): error TS1225: Cannot find parameter 'x'. +tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(30,10): error TS2391: Function implementation is missing or not immediately following the declaration. +tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(31,5): error TS1131: Property or signature expected. +tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(32,1): error TS1128: Declaration or statement expected. +tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(34,38): error TS1225: Cannot find parameter 'x'. +tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(38,51): error TS2322: Type 'B' is not assignable to type 'A'. Property 'propA' is missing in type 'B'. -tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(38,56): error TS2322: Type 'number' is not assignable to type 'string'. -tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(42,56): error TS2322: Type 'T[]' is not assignable to type 'string'. -tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(56,7): error TS2339: Property 'propB' does not exist on type 'A'. -tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(61,7): error TS2339: Property 'propB' does not exist on type 'A'. -tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(66,7): error TS2339: Property 'propB' does not exist on type 'A'. -tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(71,46): error TS2345: Argument of type '(p1: any) => boolean' is not assignable to parameter of type '(p1: any) => boolean'. +tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(42,56): error TS2322: Type 'number' is not assignable to type 'string'. +tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(46,56): error TS2322: Type 'T[]' is not assignable to type 'string'. +tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(60,7): error TS2339: Property 'propB' does not exist on type 'A'. +tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(65,7): error TS2339: Property 'propB' does not exist on type 'A'. +tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(70,7): error TS2339: Property 'propB' does not exist on type 'A'. +tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(75,46): error TS2345: Argument of type '(p1: any) => boolean' is not assignable to parameter of type '(p1: any) => boolean'. Type predicate 'p1 is C' is not assignable to 'p1 is B'. Type 'C' is not assignable to type 'B'. -tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(75,1): error TS2322: Type '(p1: any, p2: any) => boolean' is not assignable to type '(p1: any, p2: any) => boolean'. +tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(79,1): error TS2322: Type '(p1: any, p2: any) => boolean' is not assignable to type '(p1: any, p2: any) => boolean'. Signature '(p1: any, p2: any): boolean' must have a type predicate. -tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(81,1): error TS2322: Type '(p1: any, p2: any) => boolean' is not assignable to type '(p1: any, p2: any) => boolean'. +tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(85,1): error TS2322: Type '(p1: any, p2: any) => boolean' is not assignable to type '(p1: any, p2: any) => boolean'. Type predicate 'p2 is A' is not assignable to 'p1 is A'. Parameter 'p2' is not in the same position as parameter 'p1'. -tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(87,1): error TS2322: Type '(p1: any, p2: any, p3: any) => boolean' is not assignable to type '(p1: any, p2: any) => boolean'. -tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(92,9): error TS1228: A type predicate is only allowed in return type position for functions and methods. -tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(93,16): error TS1228: A type predicate is only allowed in return type position for functions and methods. -tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(94,20): error TS1228: A type predicate is only allowed in return type position for functions and methods. -tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(100,25): error TS1228: A type predicate is only allowed in return type position for functions and methods. -tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(101,16): error TS2409: Return type of constructor signature must be assignable to the instance type of the class -tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(103,20): error TS1228: A type predicate is only allowed in return type position for functions and methods. -tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(106,20): error TS1228: A type predicate is only allowed in return type position for functions and methods. -tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(107,16): error TS2408: Setters cannot return a value. -tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(112,18): error TS1228: A type predicate is only allowed in return type position for functions and methods. -tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(116,22): error TS1228: A type predicate is only allowed in return type position for functions and methods. -tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(120,20): error TS1229: A type predicate cannot reference a rest parameter. -tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(125,34): error TS1230: A type predicate cannot reference element 'p1' in a binding pattern. +tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(91,1): error TS2322: Type '(p1: any, p2: any, p3: any) => boolean' is not assignable to type '(p1: any, p2: any) => boolean'. +tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(96,9): error TS1228: A type predicate is only allowed in return type position for functions and methods. +tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(97,16): error TS1228: A type predicate is only allowed in return type position for functions and methods. +tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(98,20): error TS1228: A type predicate is only allowed in return type position for functions and methods. +tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(104,25): error TS1228: A type predicate is only allowed in return type position for functions and methods. +tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(105,16): error TS2409: Return type of constructor signature must be assignable to the instance type of the class +tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(107,20): error TS1228: A type predicate is only allowed in return type position for functions and methods. +tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(110,20): error TS1228: A type predicate is only allowed in return type position for functions and methods. +tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(111,16): error TS2408: Setters cannot return a value. +tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(116,18): error TS1228: A type predicate is only allowed in return type position for functions and methods. +tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(120,22): error TS1228: A type predicate is only allowed in return type position for functions and methods. +tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(124,20): error TS1229: A type predicate cannot reference a rest parameter. tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(129,34): error TS1230: A type predicate cannot reference element 'p1' in a binding pattern. -tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(133,39): error TS1230: A type predicate cannot reference element 'p1' in a binding pattern. +tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(133,34): error TS1230: A type predicate cannot reference element 'p1' in a binding pattern. +tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(137,39): error TS1230: A type predicate cannot reference element 'p1' in a binding pattern. -==== tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts (30 errors) ==== +==== tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts (31 errors) ==== class A { propA: number; @@ -66,6 +67,12 @@ tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(133,39 return true; } + function hasMissingParameter(): x is A { + ~ +!!! error TS1225: Cannot find parameter 'x'. + return true; + } + function hasMissingTypeInTypeGuardType(x): x is { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ !!! error TS2391: Function implementation is missing or not immediately following the declaration. @@ -237,4 +244,10 @@ tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(133,39 ~~ !!! error TS1230: A type predicate cannot reference element 'p1' in a binding pattern. return true; + } + + // Should not crash the compiler + var x: A; + if (hasMissingParameter()) { + x.propA; } \ No newline at end of file diff --git a/tests/baselines/reference/typeGuardFunctionErrors.js b/tests/baselines/reference/typeGuardFunctionErrors.js index 5b0979ac576..4923f544345 100644 --- a/tests/baselines/reference/typeGuardFunctionErrors.js +++ b/tests/baselines/reference/typeGuardFunctionErrors.js @@ -24,6 +24,10 @@ function hasMissingIsKeyword(): x { return true; } +function hasMissingParameter(): x is A { + return true; +} + function hasMissingTypeInTypeGuardType(x): x is { return true; } @@ -133,6 +137,12 @@ function b6([a, b, p1], p2, p3): p1 is A { function b7({a, b, c: {p1}}, p2, p3): p1 is A { return true; +} + +// Should not crash the compiler +var x: A; +if (hasMissingParameter()) { + x.propA; } //// [typeGuardFunctionErrors.js] @@ -167,6 +177,9 @@ function hasTypeGuardTypeInsideTypeGuardType(x) { function hasMissingIsKeyword() { return true; } +function hasMissingParameter() { + return true; +} return true; function hasNonMatchingParameter(y) { return true; @@ -260,3 +273,8 @@ function b7(_a, p2, p3) { var a = _a.a, b = _a.b, p1 = _a.c.p1; return true; } +// Should not crash the compiler +var x; +if (hasMissingParameter()) { + x.propA; +} diff --git a/tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts b/tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts index e157b2afe36..688099280c5 100644 --- a/tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts +++ b/tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts @@ -23,6 +23,10 @@ function hasMissingIsKeyword(): x { return true; } +function hasMissingParameter(): x is A { + return true; +} + function hasMissingTypeInTypeGuardType(x): x is { return true; } @@ -132,4 +136,10 @@ function b6([a, b, p1], p2, p3): p1 is A { function b7({a, b, c: {p1}}, p2, p3): p1 is A { return true; +} + +// Should not crash the compiler +var x: A; +if (hasMissingParameter()) { + x.propA; } \ No newline at end of file diff --git a/tests/cases/fourslash/syntacticClassificationsDocComment3.ts b/tests/cases/fourslash/syntacticClassificationsDocComment3.ts index bdc7faa470e..6aca8cc415f 100644 --- a/tests/cases/fourslash/syntacticClassificationsDocComment3.ts +++ b/tests/cases/fourslash/syntacticClassificationsDocComment3.ts @@ -14,7 +14,6 @@ verify.syntacticClassificationsAre( c.punctuation("{"), c.keyword("number"), c.comment(" /* } */"), - c.comment("/* } */"), c.keyword("var"), c.text("v"), c.punctuation(";")); diff --git a/tests/cases/unittests/incrementalParser.ts b/tests/cases/unittests/incrementalParser.ts index a0b361a87f4..1ef10eaa712 100644 --- a/tests/cases/unittests/incrementalParser.ts +++ b/tests/cases/unittests/incrementalParser.ts @@ -713,6 +713,24 @@ module m3 { }\ compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, 4); }); + it('Do not move constructors from class to object-literal.', () => { + var source = "class C { public constructor() { } public constructor() { } public constructor() { } }" + + var oldText = ScriptSnapshot.fromString(source); + var newTextAndChange = withChange(oldText, 0, "class C".length, "var v ="); + + compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, 0); + }); + + it('Do not move methods called "constructor" from object literal to class', () => { + var source = "var v = { public constructor() { } public constructor() { } public constructor() { } }" + + var oldText = ScriptSnapshot.fromString(source); + var newTextAndChange = withChange(oldText, 0, "var v =".length, "class C"); + + compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, 0); + }); + it('Moving index signatures from class to interface',() => { var source = "class C { public [a: number]: string; public [a: number]: string; public [a: number]: string }" diff --git a/tests/perftsc.ts b/tests/perftsc.ts index e0189896a15..89bff1cc006 100644 --- a/tests/perftsc.ts +++ b/tests/perftsc.ts @@ -10,7 +10,7 @@ if (perftest.hasLogIOFlag()) { var content = perftest.readFile(s); return content !== undefined ? ts.createSourceFile(s, content, v) : undefined; }, - getDefaultLibFilename: () => ts.combinePaths(ts.getDirectoryPath(ts.normalizePath(perftest.getExecutingFilePath())), "lib.d.ts"), + getDefaultLibFileName: () => ts.combinePaths(ts.getDirectoryPath(ts.normalizePath(perftest.getExecutingFilePath())), "lib.d.ts"), writeFile: (f: string, content: string) => { throw new Error("Unexpected operation: writeFile"); }, getCurrentDirectory: () => perftest.getCurrentDirectory(), getCanonicalFileName: (f: string) => ts.sys.useCaseSensitiveFileNames ? f : f.toLowerCase(), @@ -19,8 +19,8 @@ if (perftest.hasLogIOFlag()) { }; var commandLine = ts.parseCommandLine(perftest.getArgsWithoutLogIOFlag()); - var program = ts.createProgram(commandLine.filenames, commandLine.options, compilerHost); - var fileNames = program.getSourceFiles().map(f => f.filename); + var program = ts.createProgram(commandLine.fileNames, commandLine.options, compilerHost); + var fileNames = program.getSourceFiles().map(f => f.fileName); perftest.writeIOLog(fileNames); } else {