Multiple telemetry debug assert failure fixes (#21886)

* Use getAllowSyntheticDefaultImports to access `--allowSyntheticDefaultImport` value

* Fix #21788: Handel missing imporotClause case

* Fix #21789: Add a defensive check to forgottenThisPropertyAccess code fix for non-identifier locations

* Do not suggest prefix with `this` if the name we are looking for is diffrent from the errorLocation

* Fix #21796: Handel case of unknown module

* Add check to capture more info for #21800

* Fix #21807: check for symbol before looking up its flags

* Fix #21812: Gracefully fail if the token is not `this`.
This commit is contained in:
Mohamed Hegazy 2018-02-12 10:34:17 -08:00 committed by GitHub
parent 611ebc7aad
commit 3fb481ff40
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 119 additions and 14 deletions

View File

@ -1496,7 +1496,7 @@ namespace ts {
}
function checkAndReportErrorForMissingPrefix(errorLocation: Node, name: __String, nameArg: __String | Identifier): boolean {
if ((errorLocation.kind === SyntaxKind.Identifier && (isTypeReferenceIdentifier(<Identifier>errorLocation)) || isInTypeQuery(errorLocation))) {
if (!isIdentifier(errorLocation) || errorLocation.escapedText !== name || isTypeReferenceIdentifier(errorLocation) || isInTypeQuery(errorLocation)) {
return false;
}

View File

@ -86,7 +86,7 @@ namespace ts.codefix {
else {
const leftExpressionType = checker.getTypeAtLocation(parent.expression);
const { symbol } = leftExpressionType;
if (!(leftExpressionType.flags & TypeFlags.Object && symbol.flags & SymbolFlags.Class)) {
if (!(symbol && leftExpressionType.flags & TypeFlags.Object && symbol.flags & SymbolFlags.Class)) {
return undefined;
}
const classDeclaration = cast(first(symbol.declarations), isClassLike);

View File

@ -34,7 +34,7 @@ namespace ts.codefix {
function getNodes(sourceFile: SourceFile, pos: number): { readonly constructor: ConstructorDeclaration, readonly superCall: ExpressionStatement } {
const token = getTokenAtPosition(sourceFile, pos, /*includeJsDocComment*/ false);
Debug.assert(token.kind === SyntaxKind.ThisKeyword);
if (token.kind !== SyntaxKind.ThisKeyword) return undefined;
const constructor = getContainingFunction(token) as ConstructorDeclaration;
const superCall = findSuperCall(constructor.body);
// figure out if the `this` access is actually inside the supercall

View File

@ -7,6 +7,9 @@ namespace ts.codefix {
getCodeActions(context) {
const { sourceFile } = context;
const token = getNode(sourceFile, context.span.start);
if (!token) {
return undefined;
}
const changes = textChanges.ChangeTracker.with(context, t => doChange(t, sourceFile, token));
return [{ description: getLocaleSpecificMessage(Diagnostics.Add_this_to_unresolved_variable), changes, fixId }];
},
@ -16,13 +19,17 @@ namespace ts.codefix {
}),
});
function getNode(sourceFile: SourceFile, pos: number): Identifier {
return cast(getTokenAtPosition(sourceFile, pos, /*includeJsDocComment*/ false), isIdentifier);
function getNode(sourceFile: SourceFile, pos: number): Identifier | undefined {
const node = getTokenAtPosition(sourceFile, pos, /*includeJsDocComment*/ false);
return isIdentifier(node) ? node : undefined;
}
function doChange(changes: textChanges.ChangeTracker, sourceFile: SourceFile, token: Identifier): void {
function doChange(changes: textChanges.ChangeTracker, sourceFile: SourceFile, token: Identifier | undefined): void {
if (!token) {
return;
}
// TODO (https://github.com/Microsoft/TypeScript/issues/21246): use shared helper
suppressLeadingAndTrailingTrivia(token);
changes.replaceNode(sourceFile, token, createPropertyAccess(createThis(), token), textChanges.useNonAdjustedPositions);
}
}
}

View File

@ -86,8 +86,8 @@ namespace ts.codefix {
if (containingFunction === undefined) {
return undefined;
}
switch (errorCode) {
switch (errorCode) {
// Parameter declarations
case Diagnostics.Parameter_0_implicitly_has_an_1_type.code:
if (isSetAccessor(containingFunction)) {
@ -96,7 +96,7 @@ namespace ts.codefix {
// falls through
case Diagnostics.Rest_parameter_0_implicitly_has_an_any_type.code:
return !seenFunctions || addToSeen(seenFunctions, getNodeId(containingFunction))
? getCodeActionForParameters(<ParameterDeclaration>token.parent, containingFunction, sourceFile, program, cancellationToken)
? getCodeActionForParameters(cast(token.parent, isParameter), containingFunction, sourceFile, program, cancellationToken)
: undefined;
// Get Accessor declarations

View File

@ -7,7 +7,7 @@ namespace ts.refactor.installTypesForPackage {
function getAvailableActions(context: RefactorContext): ApplicableRefactorInfo[] | undefined {
const { file, startPosition, program } = context;
if (!program.getCompilerOptions().allowSyntheticDefaultImports) {
if (!getAllowSyntheticDefaultImports(program.getCompilerOptions())) {
return undefined;
}
@ -17,8 +17,8 @@ namespace ts.refactor.installTypesForPackage {
}
const module = getResolvedModule(file, importInfo.moduleSpecifier.text);
const resolvedFile = program.getSourceFile(module.resolvedFileName);
if (!(resolvedFile.externalModuleIndicator && isExportAssignment(resolvedFile.externalModuleIndicator) && resolvedFile.externalModuleIndicator.isExportEquals)) {
const resolvedFile = module && program.getSourceFile(module.resolvedFileName);
if (!(resolvedFile && resolvedFile.externalModuleIndicator && isExportAssignment(resolvedFile.externalModuleIndicator) && resolvedFile.externalModuleIndicator.isExportEquals)) {
return undefined;
}
@ -69,7 +69,7 @@ namespace ts.refactor.installTypesForPackage {
case SyntaxKind.ImportDeclaration:
const d = node as ImportDeclaration;
const { importClause } = d;
return !importClause.name && importClause.namedBindings.kind === SyntaxKind.NamespaceImport && isStringLiteral(d.moduleSpecifier)
return importClause && !importClause.name && importClause.namedBindings.kind === SyntaxKind.NamespaceImport && isStringLiteral(d.moduleSpecifier)
? { importStatement: d, name: importClause.namedBindings.name, moduleSpecifier: d.moduleSpecifier }
: undefined;
// For known child node kinds of convertible imports, try again with parent node.

View File

@ -0,0 +1,12 @@
tests/cases/compiler/test.tsx(3,17): error TS2304: Cannot find name 'factory'.
==== tests/cases/compiler/test.tsx (1 errors) ====
export class C {
factory() {
return <div></div>;
~~~
!!! error TS2304: Cannot find name 'factory'.
}
}

View File

@ -0,0 +1,17 @@
//// [test.tsx]
export class C {
factory() {
return <div></div>;
}
}
//// [test.js]
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
class C {
factory() {
return factory.createElement("div", null);
}
}
exports.C = C;

View File

@ -0,0 +1,11 @@
=== tests/cases/compiler/test.tsx ===
export class C {
>C : Symbol(C, Decl(test.tsx, 0, 0))
factory() {
>factory : Symbol(C.factory, Decl(test.tsx, 0, 16))
return <div></div>;
}
}

View File

@ -0,0 +1,14 @@
=== tests/cases/compiler/test.tsx ===
export class C {
>C : C
factory() {
>factory : () => any
return <div></div>;
><div></div> : any
>div : any
>div : any
}
}

View File

@ -0,0 +1,11 @@
//@jsx: react
//@target: es6
//@module: commonjs
//@reactNamespace: factory
//@filename: test.tsx
export class C {
factory() {
return <div></div>;
}
}

View File

@ -0,0 +1,7 @@
/// <reference path='fourslash.ts' />
// @Filename: a.ts
////declare var x: [1, 2];
////x.b;
verify.not.codeFixAvailable();

View File

@ -0,0 +1,14 @@
/// <reference path='fourslash.ts' />
// @jsx: react
// @jsxFactory: factory
// @Filename: /a.tsx
////export class C {
//// foo() {
//// return <a.div />;
//// }
////}
verify.not.codeFixAvailable();

View File

@ -181,7 +181,7 @@ declare namespace FourSlashInterface {
errorCode?: number,
index?: number,
});
codeFixAvailable(options: Array<{ description: string, actions?: Array<{ type: string, data: {} }>, commands?: {}[] }>): void;
codeFixAvailable(options?: Array<{ description: string, actions?: Array<{ type: string, data: {} }>, commands?: {}[] }>): void;
applicableRefactorAvailableAtMarker(markerName: string): void;
codeFixDiagnosticsAvailableAtMarkers(markerNames: string[], diagnosticCode?: number): void;
applicableRefactorAvailableForRange(): void;

View File

@ -12,6 +12,12 @@
// @Filename: /c.ts
/////*c0*/import a = require("./a");/*c1*/
// @Filename: /d.ts
/////*d0*/import "./a";/*d1*/
// @Filename: /e.ts
/////*e0*/import * as n from "./non-existant";/*e1*/
goTo.select("b0", "b1");
edit.applyRefactor({
refactorName: "Convert to default import",
@ -27,3 +33,9 @@ edit.applyRefactor({
actionDescription: "Convert to default import",
newContent: 'import a from "./a";',
});
goTo.select("d0", "d1");
verify.not.applicableRefactorAvailableAtMarker("d0");
goTo.select("e0", "e1");
verify.not.applicableRefactorAvailableAtMarker("e0");