Skip to content

Ensure TypeChecker#getTypeAtLocation returns a defined result #25583

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
3 commits merged into from
Jul 11, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 7 additions & 7 deletions src/compiler/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18834,7 +18834,7 @@ namespace ts {
node.kind === SyntaxKind.SetAccessor) {
// The `descriptor` for a method decorator will be a `TypedPropertyDescriptor<T>`
// for the type of the member.
const propertyType = getTypeOfNode(node)!; // TODO: GH#18217
const propertyType = getTypeOfNode(node);
return createTypedPropertyDescriptorType(propertyType);
}

Expand Down Expand Up @@ -21849,7 +21849,7 @@ namespace ts {
else {
const leadingError = () => chainDiagnosticMessages(/*details*/ undefined, Diagnostics.A_type_predicate_s_type_must_be_assignable_to_its_parameter_s_type);
checkTypeAssignableTo(typePredicate.type,
getTypeOfNode(parent.parameters[typePredicate.parameterIndex])!, // TODO: GH#18217
getTypeOfNode(parent.parameters[typePredicate.parameterIndex]),
node.type,
/*headMessage*/ undefined,
leadingError);
Expand Down Expand Up @@ -23181,7 +23181,7 @@ namespace ts {
case SyntaxKind.MethodDeclaration:
case SyntaxKind.GetAccessor:
case SyntaxKind.SetAccessor:
const methodType = getTypeOfNode(node.parent)!; // TODO: GH#18217
const methodType = getTypeOfNode(node.parent);
const descriptorType = createTypedPropertyDescriptorType(methodType);
expectedReturnType = getUnionType([descriptorType, voidType]);
break;
Expand Down Expand Up @@ -27120,7 +27120,7 @@ namespace ts {
resolveEntityName(node.propertyName || node.name, SymbolFlags.Value | SymbolFlags.Type | SymbolFlags.Namespace | SymbolFlags.Alias);
}

function getTypeOfNode(node: Node): Type | undefined {
function getTypeOfNode(node: Node): Type {
if (node.flags & NodeFlags.InWithStatement) {
// We cannot answer semantic questions within a with block, do not proceed any further
return errorType;
Expand Down Expand Up @@ -27159,7 +27159,7 @@ namespace ts {

if (isTypeDeclarationName(node)) {
const symbol = getSymbolAtLocation(node);
return symbol && getDeclaredTypeOfSymbol(symbol);
return symbol ? getDeclaredTypeOfSymbol(symbol) : errorType;
}

if (isDeclaration(node)) {
Expand All @@ -27170,11 +27170,11 @@ namespace ts {

if (isDeclarationNameOrImportPropertyName(node)) {
const symbol = getSymbolAtLocation(node);
return symbol && getTypeOfSymbol(symbol);
return symbol ? getTypeOfSymbol(symbol) : errorType;
}

if (isBindingPattern(node)) {
return getTypeForVariableLikeDeclaration(node.parent, /*includeOptionality*/ true);
return getTypeForVariableLikeDeclaration(node.parent, /*includeOptionality*/ true) || errorType;
}

if (isInRightSideOfImportOrExportAssignment(<Identifier>node)) {
Expand Down
2 changes: 1 addition & 1 deletion src/compiler/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2936,7 +2936,7 @@ namespace ts {
*/
getExportSymbolOfSymbol(symbol: Symbol): Symbol;
getPropertySymbolOfDestructuringAssignment(location: Identifier): Symbol | undefined;
getTypeAtLocation(node: Node): Type | undefined;
getTypeAtLocation(node: Node): Type;
getTypeFromTypeNode(node: TypeNode): Type;

signatureToString(signature: Signature, enclosingDeclaration?: Node, flags?: TypeFormatFlags, kind?: SignatureKind): string;
Expand Down
4 changes: 2 additions & 2 deletions src/services/codefixes/fixAddMissingMember.ts
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ namespace ts.codefix {
const { parent } = token;
if (!isPropertyAccessExpression(parent)) return undefined;

const leftExpressionType = skipConstraint(checker.getTypeAtLocation(parent.expression)!);
const leftExpressionType = skipConstraint(checker.getTypeAtLocation(parent.expression));
const { symbol } = leftExpressionType;
if (!symbol || !symbol.declarations) return undefined;

Expand Down Expand Up @@ -183,7 +183,7 @@ namespace ts.codefix {
if (token.parent.parent.kind === SyntaxKind.BinaryExpression) {
const binaryExpression = token.parent.parent as BinaryExpression;
const otherExpression = token.parent === binaryExpression.left ? binaryExpression.right : binaryExpression.left;
const widenedType = checker.getWidenedType(checker.getBaseTypeOfLiteralType(checker.getTypeAtLocation(otherExpression)!)); // TODO: GH#18217
const widenedType = checker.getWidenedType(checker.getBaseTypeOfLiteralType(checker.getTypeAtLocation(otherExpression)));
typeNode = checker.typeToTypeNode(widenedType, classDeclaration);
}
return typeNode || createKeywordTypeNode(SyntaxKind.AnyKeyword);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ namespace ts.codefix {

function addMissingMembers(classDeclaration: ClassLikeDeclaration, sourceFile: SourceFile, checker: TypeChecker, changeTracker: textChanges.ChangeTracker, preferences: UserPreferences): void {
const extendsNode = getEffectiveBaseTypeNode(classDeclaration)!;
const instantiatedExtendsType = checker.getTypeAtLocation(extendsNode)!;
const instantiatedExtendsType = checker.getTypeAtLocation(extendsNode);

// Note that this is ultimately derived from a map indexed by symbol names,
// so duplicates cannot occur.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ namespace ts.codefix {
const implementedTypeSymbols = checker.getPropertiesOfType(implementedType);
const nonPrivateAndNotExistedInHeritageClauseMembers = implementedTypeSymbols.filter(and(symbolPointsToNonPrivateMember, symbol => !maybeHeritageClauseSymbol.has(symbol.escapedName)));

const classType = checker.getTypeAtLocation(classDeclaration)!;
const classType = checker.getTypeAtLocation(classDeclaration);

if (!classType.getNumberIndexType()) {
createMissingIndexSignatureDeclaration(implementedType, IndexKind.Number);
Expand Down
2 changes: 1 addition & 1 deletion src/services/codefixes/fixInvalidImportSyntax.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ namespace ts.codefix {
}

function getImportCodeFixesForExpression(context: CodeFixContext, expr: Node): CodeFixAction[] | undefined {
const type = context.program.getTypeChecker().getTypeAtLocation(expr)!; // TODO: GH#18217
const type = context.program.getTypeChecker().getTypeAtLocation(expr);
if (!(type.symbol && (type.symbol as TransientSymbol).originatingImport)) {
return [];
}
Expand Down
2 changes: 1 addition & 1 deletion src/services/codefixes/fixSpelling.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ namespace ts.codefix {
let suggestion: string | undefined;
if (isPropertyAccessExpression(node.parent) && node.parent.name === node) {
Debug.assert(node.kind === SyntaxKind.Identifier);
const containingType = checker.getTypeAtLocation(node.parent.expression)!;
const containingType = checker.getTypeAtLocation(node.parent.expression);
suggestion = checker.getSuggestionForNonexistentProperty(node as Identifier, containingType);
}
else if (isImportSpecifier(node.parent) && node.parent.name === node) {
Expand Down
8 changes: 4 additions & 4 deletions src/services/codefixes/inferFromUsage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -401,7 +401,7 @@ namespace ts.codefix {
case SyntaxKind.LessThanEqualsToken:
case SyntaxKind.GreaterThanToken:
case SyntaxKind.GreaterThanEqualsToken:
const operandType = checker.getTypeAtLocation(parent.left === node ? parent.right : parent.left)!;
const operandType = checker.getTypeAtLocation(parent.left === node ? parent.right : parent.left);
if (operandType.flags & TypeFlags.EnumLike) {
addCandidateType(usageContext, operandType);
}
Expand All @@ -412,7 +412,7 @@ namespace ts.codefix {

case SyntaxKind.PlusEqualsToken:
case SyntaxKind.PlusToken:
const otherOperandType = checker.getTypeAtLocation(parent.left === node ? parent.right : parent.left)!;
const otherOperandType = checker.getTypeAtLocation(parent.left === node ? parent.right : parent.left);
if (otherOperandType.flags & TypeFlags.EnumLike) {
addCandidateType(usageContext, otherOperandType);
}
Expand Down Expand Up @@ -472,7 +472,7 @@ namespace ts.codefix {

if (parent.arguments) {
for (const argument of parent.arguments) {
callContext.argumentTypes.push(checker.getTypeAtLocation(argument)!);
callContext.argumentTypes.push(checker.getTypeAtLocation(argument));
}
}

Expand Down Expand Up @@ -501,7 +501,7 @@ namespace ts.codefix {
return;
}
else {
const indexType = checker.getTypeAtLocation(parent)!;
const indexType = checker.getTypeAtLocation(parent);
const indexUsageContext = {};
inferTypeFromContext(parent, checker, indexUsageContext);
if (indexType.flags & TypeFlags.NumberLike) {
Expand Down
2 changes: 1 addition & 1 deletion src/services/completions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1098,7 +1098,7 @@ namespace ts.Completions {
}

if (!isTypeLocation) {
addTypeProperties(typeChecker.getTypeAtLocation(node)!);
addTypeProperties(typeChecker.getTypeAtLocation(node));
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/services/goToDefinition.ts
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ namespace ts.GoToDefinition {
// At 'x.foo', see if the type of 'x' has an index signature, and if so find its declarations.
function getDefinitionInfoForIndexSignatures(node: Node, checker: TypeChecker): DefinitionInfo[] | undefined {
if (!isPropertyAccessExpression(node.parent) || node.parent.name !== node) return;
const type = checker.getTypeAtLocation(node.parent.expression)!;
const type = checker.getTypeAtLocation(node.parent.expression);
return mapDefined(type.isUnionOrIntersection() ? type.types : [type], nonUnionType => {
const info = checker.getIndexInfoOfType(nonUnionType, IndexKind.String);
return info && info.declaration && createDefinitionFromSignatureDeclaration(checker, info.declaration);
Expand Down
6 changes: 3 additions & 3 deletions src/services/refactors/extractSymbol.ts
Original file line number Diff line number Diff line change
Expand Up @@ -866,7 +866,7 @@ namespace ts.refactor.extractSymbol {

// Being returned through an object literal will have widened the type.
const variableType: TypeNode | undefined = checker.typeToTypeNode(
checker.getBaseTypeOfLiteralType(checker.getTypeAtLocation(variableDeclaration)!), // TODO: GH#18217
checker.getBaseTypeOfLiteralType(checker.getTypeAtLocation(variableDeclaration)),
scope,
NodeBuilderFlags.NoTruncation);

Expand Down Expand Up @@ -1406,7 +1406,7 @@ namespace ts.refactor.extractSymbol {
const end = last(statements).end;
expressionDiagnostic = createFileDiagnostic(sourceFile, start, end - start, Messages.expressionExpected);
}
else if (checker.getTypeAtLocation(expression)!.flags & (TypeFlags.Void | TypeFlags.Never)) { // TODO: GH#18217
else if (checker.getTypeAtLocation(expression).flags & (TypeFlags.Void | TypeFlags.Never)) {
expressionDiagnostic = createDiagnosticForNode(expression, Messages.uselessConstantType);
}

Expand Down Expand Up @@ -1555,7 +1555,7 @@ namespace ts.refactor.extractSymbol {

function collectUsages(node: Node, valueUsage = Usage.Read) {
if (inGenericContext) {
const type = checker.getTypeAtLocation(node)!; // TODO: GH#18217
const type = checker.getTypeAtLocation(node);
recordTypeParameterUsages(type);
}

Expand Down
14 changes: 7 additions & 7 deletions src/services/symbolDisplay.ts
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ namespace ts.SymbolDisplay {

const useConstructSignatures = callExpressionLike.kind === SyntaxKind.NewExpression || (isCallExpression(callExpressionLike) && callExpressionLike.expression.kind === SyntaxKind.SuperKeyword);

const allSignatures = useConstructSignatures ? type!.getConstructSignatures() : type!.getCallSignatures();
const allSignatures = useConstructSignatures ? type.getConstructSignatures() : type.getCallSignatures();

if (!contains(allSignatures, signature.target) && !contains(allSignatures, signature)) {
// Get the first signature if there is one -- allSignatures may contain
Expand All @@ -184,7 +184,7 @@ namespace ts.SymbolDisplay {
if (useConstructSignatures && (symbolFlags & SymbolFlags.Class)) {
// Constructor
symbolKind = ScriptElementKind.constructorImplementationElement;
addPrefixForAnyFunctionOrVar(type!.symbol, symbolKind);
addPrefixForAnyFunctionOrVar(type.symbol, symbolKind);
}
else if (symbolFlags & SymbolFlags.Alias) {
symbolKind = ScriptElementKind.alias;
Expand All @@ -211,8 +211,8 @@ namespace ts.SymbolDisplay {
// If it is call or construct signature of lambda's write type name
displayParts.push(punctuationPart(SyntaxKind.ColonToken));
displayParts.push(spacePart());
if (!(getObjectFlags(type!) & ObjectFlags.Anonymous) && type!.symbol) {
addRange(displayParts, symbolToDisplayParts(typeChecker, type!.symbol, enclosingDeclaration, /*meaning*/ undefined, SymbolFormatFlags.AllowAnyNodeKind | SymbolFormatFlags.WriteTypeParametersOrArguments));
if (!(getObjectFlags(type) & ObjectFlags.Anonymous) && type.symbol) {
addRange(displayParts, symbolToDisplayParts(typeChecker, type.symbol, enclosingDeclaration, /*meaning*/ undefined, SymbolFormatFlags.AllowAnyNodeKind | SymbolFormatFlags.WriteTypeParametersOrArguments));
displayParts.push(lineBreakPart());
}
if (useConstructSignatures) {
Expand All @@ -238,7 +238,7 @@ namespace ts.SymbolDisplay {
declaration === (location.kind === SyntaxKind.ConstructorKeyword ? functionDeclaration.parent : functionDeclaration));

if (locationIsSymbolDeclaration) {
const allSignatures = functionDeclaration.kind === SyntaxKind.Constructor ? type!.getNonNullableType().getConstructSignatures() : type!.getNonNullableType().getCallSignatures();
const allSignatures = functionDeclaration.kind === SyntaxKind.Constructor ? type.getNonNullableType().getConstructSignatures() : type.getNonNullableType().getCallSignatures();
if (!typeChecker.isImplementationOfOverload(functionDeclaration)) {
signature = typeChecker.getSignatureFromDeclaration(functionDeclaration)!; // TODO: GH#18217
}
Expand All @@ -249,12 +249,12 @@ namespace ts.SymbolDisplay {
if (functionDeclaration.kind === SyntaxKind.Constructor) {
// show (constructor) Type(...) signature
symbolKind = ScriptElementKind.constructorImplementationElement;
addPrefixForAnyFunctionOrVar(type!.symbol, symbolKind);
addPrefixForAnyFunctionOrVar(type.symbol, symbolKind);
}
else {
// (function/method) symbol(..signature)
addPrefixForAnyFunctionOrVar(functionDeclaration.kind === SyntaxKind.CallSignature &&
!(type!.symbol.flags & SymbolFlags.TypeLiteral || type!.symbol.flags & SymbolFlags.ObjectLiteral) ? type!.symbol : symbol, symbolKind);
!(type.symbol.flags & SymbolFlags.TypeLiteral || type.symbol.flags & SymbolFlags.ObjectLiteral) ? type.symbol : symbol, symbolKind);
}

addSignatureDisplayParts(signature, allSignatures);
Expand Down
2 changes: 1 addition & 1 deletion src/services/utilities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -925,7 +925,7 @@ namespace ts {
}

export function getPossibleGenericSignatures(called: Expression, typeArgumentCount: number, checker: TypeChecker): ReadonlyArray<Signature> {
const type = checker.getTypeAtLocation(called)!; // TODO: GH#18217
const type = checker.getTypeAtLocation(called);
const signatures = isNewExpression(called.parent) ? type.getConstructSignatures() : type.getCallSignatures();
return signatures.filter(candidate => !!candidate.typeParameters && candidate.typeParameters.length >= typeArgumentCount);
}
Expand Down
2 changes: 1 addition & 1 deletion tests/baselines/reference/api/tsserverlibrary.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1901,7 +1901,7 @@ declare namespace ts {
*/
getExportSymbolOfSymbol(symbol: Symbol): Symbol;
getPropertySymbolOfDestructuringAssignment(location: Identifier): Symbol | undefined;
getTypeAtLocation(node: Node): Type | undefined;
getTypeAtLocation(node: Node): Type;
getTypeFromTypeNode(node: TypeNode): Type;
signatureToString(signature: Signature, enclosingDeclaration?: Node, flags?: TypeFormatFlags, kind?: SignatureKind): string;
typeToString(type: Type, enclosingDeclaration?: Node, flags?: TypeFormatFlags): string;
Expand Down
2 changes: 1 addition & 1 deletion tests/baselines/reference/api/typescript.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1901,7 +1901,7 @@ declare namespace ts {
*/
getExportSymbolOfSymbol(symbol: Symbol): Symbol;
getPropertySymbolOfDestructuringAssignment(location: Identifier): Symbol | undefined;
getTypeAtLocation(node: Node): Type | undefined;
getTypeAtLocation(node: Node): Type;
getTypeFromTypeNode(node: TypeNode): Type;
signatureToString(signature: Signature, enclosingDeclaration?: Node, flags?: TypeFormatFlags, kind?: SignatureKind): string;
typeToString(type: Type, enclosingDeclaration?: Node, flags?: TypeFormatFlags): string;
Expand Down
8 changes: 4 additions & 4 deletions tests/baselines/reference/umd-errors.types
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
=== tests/cases/conformance/externalModules/err1.d.ts ===
// Illegal, can't be in script file
export as namespace Foo;
>Foo : No type information available!
>Foo : any

=== tests/cases/conformance/externalModules/err2.d.ts ===
// Illegal, can't be in external ambient module
declare module "Foo" {
>"Foo" : typeof import("Foo")

export as namespace Bar;
>Bar : No type information available!
>Bar : any
}

=== tests/cases/conformance/externalModules/err3.d.ts ===
Expand All @@ -35,7 +35,7 @@ export namespace B {
>B : typeof B

export as namespace C1;
>C1 : No type information available!
>C1 : any
}

=== tests/cases/conformance/externalModules/err5.ts ===
Expand All @@ -44,6 +44,6 @@ export var v;
>v : any

export as namespace C2;
>C2 : No type information available!
>C2 : any