mirror of
https://github.com/microsoft/TypeScript.git
synced 2025-11-18 17:21:48 +00:00
Enable '--strictNullChecks' (#22088)
* Enable '--strictNullChecks' * Fix API baselines * Make sys.getEnvironmentVariable non-nullable * make properties optional instead of using `| undefined` in thier type * reportDiagnostics should be required * Declare firstAccessor as non-nullable * Make `some` a type guard * Fix `getEnvironmentVariable` definition in tests * Pretend transformFlags are always defined * Fix one more use of sys.getEnvironmentVariable * `requiredResponse` accepts undefined, remove assertions * Mark optional properties as optional instead of using `| undefined` * Mark optional properties as optional instead of using ` | undefined` * Remove unnecessary null assertions * Put the bang on the declaration instead of every use * Make `createMapFromTemplate` require a parameter * Mark `EmitResult.emittedFiles` and `EmitResult.sourceMaps` as optional * Plumb through undefined in emitLsit and EmitExpressionList * `ElementAccessExpression.argumentExpression` can not be `undefined` * Add overloads for `writeTokenText` * Make `shouldWriteSeparatingLineTerminator` argument non-nullable * Make `synthesizedNodeStartsOnNewLine` argument required * `PropertyAssignment.initializer` cannot be undefined * Use one `!` at declaration site instead of on every use site * Capture host in a constant and avoid null assertions * Remove few more unused assertions * Update baselines * Use parameter defaults * Update baselines * Fix lint * Make Symbol#valueDeclaration and Symbol#declarations non-optional to reduce assertions * Make Node#symbol and Type#symbol non-optional to reduce assertions * Make `flags` non-nullable to reduce assertions * Convert some asserts to type guards * Make `isNonLocalAlias` a type guard * Add overload for `getSymbolOfNode` for `Declaration` * Some more `getSymbolOfNode` changes * Push undefined suppression into `typeToTypeNodeHelper` * `NodeBuilderContext.tracker` is never `undefined` * use `Debug.assertDefined` * Remove unnecessary tag * Mark `LiteralType.freshType` and `LiteralTupe.regularType` as required
This commit is contained in:
+33
-30
@@ -17,12 +17,13 @@ namespace ts.BreakpointResolver {
|
||||
// let y = 10;
|
||||
// token at position will return let keyword on second line as the token but we would like to use
|
||||
// token on same line if trailing trivia (comments or white spaces on same line) part of the last token on that line
|
||||
tokenAtLocation = findPrecedingToken(tokenAtLocation.pos, sourceFile);
|
||||
const preceding = findPrecedingToken(tokenAtLocation.pos, sourceFile);
|
||||
|
||||
// It's a blank line
|
||||
if (!tokenAtLocation || sourceFile.getLineAndCharacterOfPosition(tokenAtLocation.getEnd()).line !== lineOfPosition) {
|
||||
if (!preceding || sourceFile.getLineAndCharacterOfPosition(preceding.getEnd()).line !== lineOfPosition) {
|
||||
return undefined;
|
||||
}
|
||||
tokenAtLocation = preceding;
|
||||
}
|
||||
|
||||
// Cannot set breakpoint in ambient declarations
|
||||
@@ -44,7 +45,7 @@ namespace ts.BreakpointResolver {
|
||||
return textSpan(startNode, findNextToken(previousTokenToFindNextEndToken, previousTokenToFindNextEndToken.parent, sourceFile));
|
||||
}
|
||||
|
||||
function spanInNodeIfStartsOnSameLine(node: Node, otherwiseOnNode?: Node): TextSpan {
|
||||
function spanInNodeIfStartsOnSameLine(node: Node | undefined, otherwiseOnNode?: Node): TextSpan | undefined {
|
||||
if (node && lineOfPosition === sourceFile.getLineAndCharacterOfPosition(node.getStart(sourceFile)).line) {
|
||||
return spanInNode(node);
|
||||
}
|
||||
@@ -55,16 +56,17 @@ namespace ts.BreakpointResolver {
|
||||
return createTextSpanFromBounds(skipTrivia(sourceFile.text, nodeArray.pos), nodeArray.end);
|
||||
}
|
||||
|
||||
function spanInPreviousNode(node: Node): TextSpan {
|
||||
function spanInPreviousNode(node: Node): TextSpan | undefined {
|
||||
return spanInNode(findPrecedingToken(node.pos, sourceFile));
|
||||
}
|
||||
|
||||
function spanInNextNode(node: Node): TextSpan {
|
||||
function spanInNextNode(node: Node): TextSpan | undefined {
|
||||
return spanInNode(findNextToken(node, node.parent, sourceFile));
|
||||
}
|
||||
|
||||
function spanInNode(node: Node): TextSpan {
|
||||
function spanInNode(node: Node | undefined): TextSpan | undefined {
|
||||
if (node) {
|
||||
const { parent } = node;
|
||||
switch (node.kind) {
|
||||
case SyntaxKind.VariableStatement:
|
||||
// Span on first variable declaration
|
||||
@@ -195,7 +197,7 @@ namespace ts.BreakpointResolver {
|
||||
return spanInNode((<WithStatement>node).statement);
|
||||
|
||||
case SyntaxKind.Decorator:
|
||||
return spanInNodeArray(node.parent.decorators);
|
||||
return spanInNodeArray(parent.decorators!);
|
||||
|
||||
case SyntaxKind.ObjectBindingPattern:
|
||||
case SyntaxKind.ArrayBindingPattern:
|
||||
@@ -263,7 +265,7 @@ namespace ts.BreakpointResolver {
|
||||
node.kind === SyntaxKind.SpreadElement ||
|
||||
node.kind === SyntaxKind.PropertyAssignment ||
|
||||
node.kind === SyntaxKind.ShorthandPropertyAssignment) &&
|
||||
isArrayLiteralOrObjectLiteralDestructuringPattern(node.parent)) {
|
||||
isArrayLiteralOrObjectLiteralDestructuringPattern(parent)) {
|
||||
return textSpan(node);
|
||||
}
|
||||
|
||||
@@ -292,7 +294,7 @@ namespace ts.BreakpointResolver {
|
||||
}
|
||||
|
||||
if (isExpressionNode(node)) {
|
||||
switch (node.parent.kind) {
|
||||
switch (parent.kind) {
|
||||
case SyntaxKind.DoStatement:
|
||||
// Set span as if on while keyword
|
||||
return spanInPreviousNode(node);
|
||||
@@ -367,7 +369,7 @@ namespace ts.BreakpointResolver {
|
||||
function textSpanFromVariableDeclaration(variableDeclaration: VariableDeclaration | PropertyDeclaration | PropertySignature): TextSpan {
|
||||
if (isVariableDeclarationList(variableDeclaration.parent) && variableDeclaration.parent.declarations[0] === variableDeclaration) {
|
||||
// First declaration - include let keyword
|
||||
return textSpan(findPrecedingToken(variableDeclaration.pos, sourceFile, variableDeclaration.parent), variableDeclaration);
|
||||
return textSpan(findPrecedingToken(variableDeclaration.pos, sourceFile, variableDeclaration.parent)!, variableDeclaration);
|
||||
}
|
||||
else {
|
||||
// Span only on this declaration
|
||||
@@ -375,12 +377,13 @@ namespace ts.BreakpointResolver {
|
||||
}
|
||||
}
|
||||
|
||||
function spanInVariableDeclaration(variableDeclaration: VariableDeclaration | PropertyDeclaration | PropertySignature): TextSpan {
|
||||
function spanInVariableDeclaration(variableDeclaration: VariableDeclaration | PropertyDeclaration | PropertySignature): TextSpan | undefined {
|
||||
// If declaration of for in statement, just set the span in parent
|
||||
if (variableDeclaration.parent.parent.kind === SyntaxKind.ForInStatement) {
|
||||
return spanInNode(variableDeclaration.parent.parent);
|
||||
}
|
||||
|
||||
const parent = variableDeclaration.parent;
|
||||
// If this is a destructuring pattern, set breakpoint in binding pattern
|
||||
if (isBindingPattern(variableDeclaration.name)) {
|
||||
return spanInBindingPattern(variableDeclaration.name);
|
||||
@@ -390,7 +393,7 @@ namespace ts.BreakpointResolver {
|
||||
// or its declaration from 'for of'
|
||||
if (variableDeclaration.initializer ||
|
||||
hasModifier(variableDeclaration, ModifierFlags.Export) ||
|
||||
variableDeclaration.parent.parent.kind === SyntaxKind.ForOfStatement) {
|
||||
parent.parent.kind === SyntaxKind.ForOfStatement) {
|
||||
return textSpanFromVariableDeclaration(variableDeclaration);
|
||||
}
|
||||
|
||||
@@ -410,7 +413,7 @@ namespace ts.BreakpointResolver {
|
||||
hasModifier(parameter, ModifierFlags.Public | ModifierFlags.Private);
|
||||
}
|
||||
|
||||
function spanInParameterDeclaration(parameter: ParameterDeclaration): TextSpan {
|
||||
function spanInParameterDeclaration(parameter: ParameterDeclaration): TextSpan | undefined {
|
||||
if (isBindingPattern(parameter.name)) {
|
||||
// Set breakpoint in binding pattern
|
||||
return spanInBindingPattern(parameter.name);
|
||||
@@ -438,7 +441,7 @@ namespace ts.BreakpointResolver {
|
||||
(functionDeclaration.parent.kind === SyntaxKind.ClassDeclaration && functionDeclaration.kind !== SyntaxKind.Constructor);
|
||||
}
|
||||
|
||||
function spanInFunctionDeclaration(functionDeclaration: FunctionLikeDeclaration): TextSpan {
|
||||
function spanInFunctionDeclaration(functionDeclaration: FunctionLikeDeclaration): TextSpan | undefined {
|
||||
// No breakpoints in the function signature
|
||||
if (!functionDeclaration.body) {
|
||||
return undefined;
|
||||
@@ -453,7 +456,7 @@ namespace ts.BreakpointResolver {
|
||||
return spanInNode(functionDeclaration.body);
|
||||
}
|
||||
|
||||
function spanInFunctionBlock(block: Block): TextSpan {
|
||||
function spanInFunctionBlock(block: Block): TextSpan | undefined {
|
||||
const nodeForSpanInBlock = block.statements.length ? block.statements[0] : block.getLastToken();
|
||||
if (canFunctionHaveSpanInWholeDeclaration(<FunctionLikeDeclaration>block.parent)) {
|
||||
return spanInNodeIfStartsOnSameLine(block.parent, nodeForSpanInBlock);
|
||||
@@ -462,7 +465,7 @@ namespace ts.BreakpointResolver {
|
||||
return spanInNode(nodeForSpanInBlock);
|
||||
}
|
||||
|
||||
function spanInBlock(block: Block): TextSpan {
|
||||
function spanInBlock(block: Block): TextSpan | undefined {
|
||||
switch (block.parent.kind) {
|
||||
case SyntaxKind.ModuleDeclaration:
|
||||
if (getModuleInstanceState(block.parent as ModuleDeclaration) !== ModuleInstanceState.Instantiated) {
|
||||
@@ -486,8 +489,8 @@ namespace ts.BreakpointResolver {
|
||||
return spanInNode(block.statements[0]);
|
||||
}
|
||||
|
||||
function spanInInitializerOfForLike(forLikeStatement: ForStatement | ForOfStatement | ForInStatement): TextSpan {
|
||||
if (forLikeStatement.initializer.kind === SyntaxKind.VariableDeclarationList) {
|
||||
function spanInInitializerOfForLike(forLikeStatement: ForStatement | ForOfStatement | ForInStatement): TextSpan | undefined {
|
||||
if (forLikeStatement.initializer!.kind === SyntaxKind.VariableDeclarationList) {
|
||||
// Declaration list - set breakpoint in first declaration
|
||||
const variableDeclarationList = <VariableDeclarationList>forLikeStatement.initializer;
|
||||
if (variableDeclarationList.declarations.length > 0) {
|
||||
@@ -500,7 +503,7 @@ namespace ts.BreakpointResolver {
|
||||
}
|
||||
}
|
||||
|
||||
function spanInForStatement(forStatement: ForStatement): TextSpan {
|
||||
function spanInForStatement(forStatement: ForStatement): TextSpan | undefined {
|
||||
if (forStatement.initializer) {
|
||||
return spanInInitializerOfForLike(forStatement);
|
||||
}
|
||||
@@ -513,7 +516,7 @@ namespace ts.BreakpointResolver {
|
||||
}
|
||||
}
|
||||
|
||||
function spanInBindingPattern(bindingPattern: BindingPattern): TextSpan {
|
||||
function spanInBindingPattern(bindingPattern: BindingPattern): TextSpan | undefined {
|
||||
// Set breakpoint in first binding element
|
||||
const firstBindingElement = forEach(bindingPattern.elements,
|
||||
element => element.kind !== SyntaxKind.OmittedExpression ? element : undefined);
|
||||
@@ -531,7 +534,7 @@ namespace ts.BreakpointResolver {
|
||||
return textSpanFromVariableDeclaration(<VariableDeclaration>bindingPattern.parent);
|
||||
}
|
||||
|
||||
function spanInArrayLiteralOrObjectLiteralDestructuringPattern(node: DestructuringPattern): TextSpan {
|
||||
function spanInArrayLiteralOrObjectLiteralDestructuringPattern(node: DestructuringPattern): TextSpan | undefined {
|
||||
Debug.assert(node.kind !== SyntaxKind.ArrayBindingPattern && node.kind !== SyntaxKind.ObjectBindingPattern);
|
||||
const elements: NodeArray<Expression | ObjectLiteralElement> = node.kind === SyntaxKind.ArrayLiteralExpression ? node.elements : (node as ObjectLiteralExpression).properties;
|
||||
|
||||
@@ -550,7 +553,7 @@ namespace ts.BreakpointResolver {
|
||||
}
|
||||
|
||||
// Tokens:
|
||||
function spanInOpenBraceToken(node: Node): TextSpan {
|
||||
function spanInOpenBraceToken(node: Node): TextSpan | undefined {
|
||||
switch (node.parent.kind) {
|
||||
case SyntaxKind.EnumDeclaration:
|
||||
const enumDeclaration = <EnumDeclaration>node.parent;
|
||||
@@ -568,7 +571,7 @@ namespace ts.BreakpointResolver {
|
||||
return spanInNode(node.parent);
|
||||
}
|
||||
|
||||
function spanInCloseBraceToken(node: Node): TextSpan {
|
||||
function spanInCloseBraceToken(node: Node): TextSpan | undefined {
|
||||
switch (node.parent.kind) {
|
||||
case SyntaxKind.ModuleBlock:
|
||||
// If this is not an instantiated module block, no bp span
|
||||
@@ -617,7 +620,7 @@ namespace ts.BreakpointResolver {
|
||||
}
|
||||
}
|
||||
|
||||
function spanInCloseBracketToken(node: Node): TextSpan {
|
||||
function spanInCloseBracketToken(node: Node): TextSpan | undefined {
|
||||
switch (node.parent.kind) {
|
||||
case SyntaxKind.ArrayBindingPattern:
|
||||
// Breakpoint in last binding element or binding pattern if it contains no elements
|
||||
@@ -636,7 +639,7 @@ namespace ts.BreakpointResolver {
|
||||
}
|
||||
}
|
||||
|
||||
function spanInOpenParenToken(node: Node): TextSpan {
|
||||
function spanInOpenParenToken(node: Node): TextSpan | undefined {
|
||||
if (node.parent.kind === SyntaxKind.DoStatement || // Go to while keyword and do action instead
|
||||
node.parent.kind === SyntaxKind.CallExpression ||
|
||||
node.parent.kind === SyntaxKind.NewExpression) {
|
||||
@@ -651,7 +654,7 @@ namespace ts.BreakpointResolver {
|
||||
return spanInNode(node.parent);
|
||||
}
|
||||
|
||||
function spanInCloseParenToken(node: Node): TextSpan {
|
||||
function spanInCloseParenToken(node: Node): TextSpan | undefined {
|
||||
// Is this close paren token of parameter list, set span in previous token
|
||||
switch (node.parent.kind) {
|
||||
case SyntaxKind.FunctionExpression:
|
||||
@@ -677,7 +680,7 @@ namespace ts.BreakpointResolver {
|
||||
}
|
||||
}
|
||||
|
||||
function spanInColonToken(node: Node): TextSpan {
|
||||
function spanInColonToken(node: Node): TextSpan | undefined {
|
||||
// Is this : specifying return annotation of the function declaration
|
||||
if (isFunctionLike(node.parent) ||
|
||||
node.parent.kind === SyntaxKind.PropertyAssignment ||
|
||||
@@ -688,7 +691,7 @@ namespace ts.BreakpointResolver {
|
||||
return spanInNode(node.parent);
|
||||
}
|
||||
|
||||
function spanInGreaterThanOrLessThanToken(node: Node): TextSpan {
|
||||
function spanInGreaterThanOrLessThanToken(node: Node): TextSpan | undefined {
|
||||
if (node.parent.kind === SyntaxKind.TypeAssertionExpression) {
|
||||
return spanInNextNode(node);
|
||||
}
|
||||
@@ -696,7 +699,7 @@ namespace ts.BreakpointResolver {
|
||||
return spanInNode(node.parent);
|
||||
}
|
||||
|
||||
function spanInWhileKeyword(node: Node): TextSpan {
|
||||
function spanInWhileKeyword(node: Node): TextSpan | undefined {
|
||||
if (node.parent.kind === SyntaxKind.DoStatement) {
|
||||
// Set span on while expression
|
||||
return textSpanEndingAtNextToken(node, (<DoStatement>node.parent).expression);
|
||||
@@ -706,7 +709,7 @@ namespace ts.BreakpointResolver {
|
||||
return spanInNode(node.parent);
|
||||
}
|
||||
|
||||
function spanInOfKeyword(node: Node): TextSpan {
|
||||
function spanInOfKeyword(node: Node): TextSpan | undefined {
|
||||
if (node.parent.kind === SyntaxKind.ForOfStatement) {
|
||||
// Set using next token
|
||||
return spanInNextNode(node);
|
||||
|
||||
+17
-12
@@ -300,6 +300,8 @@ namespace ts {
|
||||
case ClassificationType.text:
|
||||
case ClassificationType.parameterName:
|
||||
return TokenClass.Identifier;
|
||||
default:
|
||||
return undefined!; // TODO: GH#18217 Debug.assertNever(type);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -559,6 +561,7 @@ namespace ts {
|
||||
case ClassificationType.jsxAttribute: return ClassificationTypeNames.jsxAttribute;
|
||||
case ClassificationType.jsxText: return ClassificationTypeNames.jsxText;
|
||||
case ClassificationType.jsxAttributeStringLiteralValue: return ClassificationTypeNames.jsxAttributeStringLiteralValue;
|
||||
default: return undefined!; // TODO: GH#18217 throw Debug.assertNever(type);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -813,7 +816,7 @@ namespace ts {
|
||||
return true;
|
||||
}
|
||||
|
||||
function tryClassifyJsxElementName(token: Node): ClassificationType {
|
||||
function tryClassifyJsxElementName(token: Node): ClassificationType | undefined {
|
||||
switch (token.parent && token.parent.kind) {
|
||||
case SyntaxKind.JsxOpeningElement:
|
||||
if ((<JsxOpeningElement>token.parent).tagName === token) {
|
||||
@@ -842,7 +845,7 @@ namespace ts {
|
||||
// for accurate classification, the actual token should be passed in. however, for
|
||||
// cases like 'disabled merge code' classification, we just get the token kind and
|
||||
// classify based on that instead.
|
||||
function classifyTokenType(tokenKind: SyntaxKind, token?: Node): ClassificationType {
|
||||
function classifyTokenType(tokenKind: SyntaxKind, token?: Node): ClassificationType | undefined {
|
||||
if (isKeyword(tokenKind)) {
|
||||
return ClassificationType.keyword;
|
||||
}
|
||||
@@ -859,20 +862,21 @@ namespace ts {
|
||||
|
||||
if (isPunctuation(tokenKind)) {
|
||||
if (token) {
|
||||
const parent = token.parent;
|
||||
if (tokenKind === SyntaxKind.EqualsToken) {
|
||||
// the '=' in a variable declaration is special cased here.
|
||||
if (token.parent.kind === SyntaxKind.VariableDeclaration ||
|
||||
token.parent.kind === SyntaxKind.PropertyDeclaration ||
|
||||
token.parent.kind === SyntaxKind.Parameter ||
|
||||
token.parent.kind === SyntaxKind.JsxAttribute) {
|
||||
if (parent.kind === SyntaxKind.VariableDeclaration ||
|
||||
parent.kind === SyntaxKind.PropertyDeclaration ||
|
||||
parent.kind === SyntaxKind.Parameter ||
|
||||
parent.kind === SyntaxKind.JsxAttribute) {
|
||||
return ClassificationType.operator;
|
||||
}
|
||||
}
|
||||
|
||||
if (token.parent.kind === SyntaxKind.BinaryExpression ||
|
||||
token.parent.kind === SyntaxKind.PrefixUnaryExpression ||
|
||||
token.parent.kind === SyntaxKind.PostfixUnaryExpression ||
|
||||
token.parent.kind === SyntaxKind.ConditionalExpression) {
|
||||
if (parent.kind === SyntaxKind.BinaryExpression ||
|
||||
parent.kind === SyntaxKind.PrefixUnaryExpression ||
|
||||
parent.kind === SyntaxKind.PostfixUnaryExpression ||
|
||||
parent.kind === SyntaxKind.ConditionalExpression) {
|
||||
return ClassificationType.operator;
|
||||
}
|
||||
}
|
||||
@@ -883,7 +887,8 @@ namespace ts {
|
||||
return ClassificationType.numericLiteral;
|
||||
}
|
||||
else if (tokenKind === SyntaxKind.StringLiteral) {
|
||||
return token.parent.kind === SyntaxKind.JsxAttribute ? ClassificationType.jsxAttributeStringLiteralValue : ClassificationType.stringLiteral;
|
||||
// TODO: GH#18217
|
||||
return token!.parent.kind === SyntaxKind.JsxAttribute ? ClassificationType.jsxAttributeStringLiteralValue : ClassificationType.stringLiteral;
|
||||
}
|
||||
else if (tokenKind === SyntaxKind.RegularExpressionLiteral) {
|
||||
// TODO: we should get another classification type for these literals.
|
||||
@@ -935,7 +940,7 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
function processElement(element: Node) {
|
||||
function processElement(element: Node | undefined) {
|
||||
if (!element) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -73,7 +73,7 @@ namespace ts.codefix {
|
||||
node.kind === SyntaxKind.PropertyDeclaration;
|
||||
}
|
||||
|
||||
function transformJSDocType(node: TypeNode): TypeNode | undefined {
|
||||
function transformJSDocType(node: TypeNode): TypeNode {
|
||||
switch (node.kind) {
|
||||
case SyntaxKind.JSDocAllType:
|
||||
case SyntaxKind.JSDocUnknownType:
|
||||
@@ -91,7 +91,7 @@ namespace ts.codefix {
|
||||
case SyntaxKind.TypeReference:
|
||||
return transformJSDocTypeReference(node as TypeReferenceNode);
|
||||
default:
|
||||
const visited = visitEachChild(node, transformJSDocType, /*context*/ undefined);
|
||||
const visited = visitEachChild(node, transformJSDocType, /*context*/ undefined!); // TODO: GH#18217
|
||||
setEmitFlags(visited, EmitFlags.SingleLine);
|
||||
return visited;
|
||||
}
|
||||
@@ -115,7 +115,7 @@ namespace ts.codefix {
|
||||
|
||||
function transformJSDocParameter(node: ParameterDeclaration) {
|
||||
const index = node.parent.parameters.indexOf(node);
|
||||
const isRest = node.type.kind === SyntaxKind.JSDocVariadicType && index === node.parent.parameters.length - 1;
|
||||
const isRest = node.type!.kind === SyntaxKind.JSDocVariadicType && index === node.parent.parameters.length - 1; // TODO: GH#18217
|
||||
const name = node.name || (isRest ? "rest" : "arg" + index);
|
||||
const dotdotdot = isRest ? createToken(SyntaxKind.DotDotDotToken) : node.dotDotDotToken;
|
||||
return createParameter(node.decorators, node.modifiers, dotdotdot, name, node.questionToken, visitNode(node.type, transformJSDocType), node.initializer);
|
||||
@@ -158,11 +158,11 @@ namespace ts.codefix {
|
||||
/*decorators*/ undefined,
|
||||
/*modifiers*/ undefined,
|
||||
/*dotDotDotToken*/ undefined,
|
||||
node.typeArguments[0].kind === SyntaxKind.NumberKeyword ? "n" : "s",
|
||||
node.typeArguments![0].kind === SyntaxKind.NumberKeyword ? "n" : "s",
|
||||
/*questionToken*/ undefined,
|
||||
createTypeReferenceNode(node.typeArguments[0].kind === SyntaxKind.NumberKeyword ? "number" : "string", []),
|
||||
createTypeReferenceNode(node.typeArguments![0].kind === SyntaxKind.NumberKeyword ? "number" : "string", []),
|
||||
/*initializer*/ undefined);
|
||||
const indexSignature = createTypeLiteralNode([createIndexSignature(/*decorators*/ undefined, /*modifiers*/ undefined, [index], node.typeArguments[1])]);
|
||||
const indexSignature = createTypeLiteralNode([createIndexSignature(/*decorators*/ undefined, /*modifiers*/ undefined, [index], node.typeArguments![1])]);
|
||||
setEmitFlags(indexSignature, EmitFlags.SingleLine);
|
||||
return indexSignature;
|
||||
}
|
||||
|
||||
@@ -9,12 +9,12 @@ namespace ts.codefix {
|
||||
return [createCodeFixAction(fixId, changes, Diagnostics.Convert_function_to_an_ES2015_class, fixId, Diagnostics.Convert_all_constructor_functions_to_classes)];
|
||||
},
|
||||
fixIds: [fixId],
|
||||
getAllCodeActions: context => codeFixAll(context, errorCodes, (changes, err) => doChange(changes, err.file!, err.start, context.program.getTypeChecker())),
|
||||
getAllCodeActions: context => codeFixAll(context, errorCodes, (changes, err) => doChange(changes, err.file, err.start, context.program.getTypeChecker())),
|
||||
});
|
||||
|
||||
function doChange(changes: textChanges.ChangeTracker, sourceFile: SourceFile, position: number, checker: TypeChecker): void {
|
||||
const deletedNodes: { node: Node, inList: boolean }[] = [];
|
||||
const ctorSymbol = checker.getSymbolAtLocation(getTokenAtPosition(sourceFile, position, /*includeJsDocComment*/ false));
|
||||
const ctorSymbol = checker.getSymbolAtLocation(getTokenAtPosition(sourceFile, position, /*includeJsDocComment*/ false))!;
|
||||
|
||||
if (!ctorSymbol || !(ctorSymbol.flags & (SymbolFlags.Function | SymbolFlags.Variable))) {
|
||||
// Bad input
|
||||
@@ -23,8 +23,8 @@ namespace ts.codefix {
|
||||
|
||||
const ctorDeclaration = ctorSymbol.valueDeclaration;
|
||||
|
||||
let precedingNode: Node;
|
||||
let newClassDeclaration: ClassDeclaration;
|
||||
let precedingNode: Node | undefined;
|
||||
let newClassDeclaration: ClassDeclaration | undefined;
|
||||
switch (ctorDeclaration.kind) {
|
||||
case SyntaxKind.FunctionDeclaration:
|
||||
precedingNode = ctorDeclaration;
|
||||
@@ -36,7 +36,7 @@ namespace ts.codefix {
|
||||
precedingNode = ctorDeclaration.parent.parent;
|
||||
newClassDeclaration = createClassFromVariableDeclaration(ctorDeclaration as VariableDeclaration);
|
||||
if ((<VariableDeclarationList>ctorDeclaration.parent).declarations.length === 1) {
|
||||
copyComments(precedingNode, newClassDeclaration, sourceFile);
|
||||
copyComments(precedingNode, newClassDeclaration!, sourceFile); // TODO: GH#18217
|
||||
deleteNode(precedingNode);
|
||||
}
|
||||
else {
|
||||
@@ -52,7 +52,7 @@ namespace ts.codefix {
|
||||
copyComments(ctorDeclaration, newClassDeclaration, sourceFile);
|
||||
|
||||
// Because the preceding node could be touched, we need to insert nodes before delete nodes.
|
||||
changes.insertNodeAfter(sourceFile, precedingNode, newClassDeclaration);
|
||||
changes.insertNodeAfter(sourceFile, precedingNode!, newClassDeclaration);
|
||||
for (const { node, inList } of deletedNodes) {
|
||||
if (inList) {
|
||||
changes.deleteNodeInList(sourceFile, node);
|
||||
@@ -99,7 +99,7 @@ namespace ts.codefix {
|
||||
return isFunctionLike(source);
|
||||
}
|
||||
|
||||
function createClassElement(symbol: Symbol, modifiers: Modifier[]): ClassElement {
|
||||
function createClassElement(symbol: Symbol, modifiers: Modifier[] | undefined): ClassElement | undefined {
|
||||
// Right now the only thing we can convert are function expressions, which are marked as methods
|
||||
if (!(symbol.flags & SymbolFlags.Method)) {
|
||||
return;
|
||||
@@ -166,7 +166,7 @@ namespace ts.codefix {
|
||||
}
|
||||
}
|
||||
|
||||
function createClassFromVariableDeclaration(node: VariableDeclaration): ClassDeclaration {
|
||||
function createClassFromVariableDeclaration(node: VariableDeclaration): ClassDeclaration | undefined {
|
||||
const initializer = node.initializer as FunctionExpression;
|
||||
if (!initializer || initializer.kind !== SyntaxKind.FunctionExpression) {
|
||||
return undefined;
|
||||
@@ -181,7 +181,7 @@ namespace ts.codefix {
|
||||
memberElements.unshift(createConstructor(/*decorators*/ undefined, /*modifiers*/ undefined, initializer.parameters, initializer.body));
|
||||
}
|
||||
|
||||
const modifiers = getModifierKindFromSource(precedingNode, SyntaxKind.ExportKeyword);
|
||||
const modifiers = getModifierKindFromSource(precedingNode!, SyntaxKind.ExportKeyword);
|
||||
const cls = createClassDeclaration(/*decorators*/ undefined, modifiers, node.name,
|
||||
/*typeParameters*/ undefined, /*heritageClauses*/ undefined, memberElements);
|
||||
// Don't call copyComments here because we'll already leave them in place
|
||||
@@ -218,7 +218,7 @@ namespace ts.codefix {
|
||||
});
|
||||
}
|
||||
|
||||
function getModifierKindFromSource(source: Node, kind: SyntaxKind): ReadonlyArray<Modifier> {
|
||||
function getModifierKindFromSource(source: Node, kind: SyntaxKind): ReadonlyArray<Modifier> | undefined {
|
||||
return filter(source.modifiers, modifier => modifier.kind === kind);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ namespace ts.codefix {
|
||||
getCodeActions(context) {
|
||||
const { sourceFile, program } = context;
|
||||
const changes = textChanges.ChangeTracker.with(context, changes => {
|
||||
const moduleExportsChangedToDefault = convertFileToEs6Module(sourceFile, program.getTypeChecker(), changes, program.getCompilerOptions().target);
|
||||
const moduleExportsChangedToDefault = convertFileToEs6Module(sourceFile, program.getTypeChecker(), changes, program.getCompilerOptions().target!);
|
||||
if (moduleExportsChangedToDefault) {
|
||||
for (const importingFile of program.getSourceFiles()) {
|
||||
fixImportOfModuleExports(importingFile, sourceFile, changes);
|
||||
@@ -170,7 +170,7 @@ namespace ts.codefix {
|
||||
// `const a = require("b").c` --> `import { c as a } from "./b";
|
||||
return [makeSingleImport(name.text, propertyName, moduleSpecifier)];
|
||||
default:
|
||||
Debug.assertNever(name);
|
||||
return Debug.assertNever(name);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -265,7 +265,7 @@ namespace ts.codefix {
|
||||
// `module.exports = require("x");` ==> `export * from "x"; export { default } from "x";`
|
||||
const moduleSpecifier = reExported.text;
|
||||
const moduleSymbol = checker.getSymbolAtLocation(reExported);
|
||||
const exports = moduleSymbol ? moduleSymbol.exports : emptyUnderscoreEscapedMap;
|
||||
const exports = moduleSymbol ? moduleSymbol.exports! : emptyUnderscoreEscapedMap;
|
||||
return exports.has("export=" as __String)
|
||||
? [[reExportDefault(moduleSpecifier)], true]
|
||||
: !exports.has("default" as __String)
|
||||
@@ -323,7 +323,7 @@ namespace ts.codefix {
|
||||
|
||||
function exportConst() {
|
||||
// `exports.x = 0;` --> `export const x = 0;`
|
||||
return makeConst(modifiers, createIdentifier(name), exported);
|
||||
return makeConst(modifiers, createIdentifier(name!), exported); // TODO: GH#18217
|
||||
}
|
||||
}
|
||||
|
||||
@@ -346,7 +346,7 @@ namespace ts.codefix {
|
||||
const importSpecifiers = mapAllOrFail(name.elements, e =>
|
||||
e.dotDotDotToken || e.initializer || e.propertyName && !isIdentifier(e.propertyName) || !isIdentifier(e.name)
|
||||
? undefined
|
||||
: makeImportSpecifier(e.propertyName && (e.propertyName as Identifier).text, e.name.text));
|
||||
: makeImportSpecifier(e.propertyName && (e.propertyName as Identifier).text, e.name.text)); // tslint:disable-line no-unnecessary-type-assertion (TODO: GH#18217)
|
||||
if (importSpecifiers) {
|
||||
return [makeImport(/*name*/ undefined, importSpecifiers, moduleSpecifier)];
|
||||
}
|
||||
@@ -366,7 +366,7 @@ namespace ts.codefix {
|
||||
case SyntaxKind.Identifier:
|
||||
return convertSingleIdentifierImport(file, name, moduleSpecifier, changes, checker, identifiers);
|
||||
default:
|
||||
Debug.assertNever(name);
|
||||
return Debug.assertNever(name);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -381,7 +381,7 @@ namespace ts.codefix {
|
||||
// True if there is some non-property use like `x()` or `f(x)`.
|
||||
let needDefaultImport = false;
|
||||
|
||||
for (const use of identifiers.original.get(name.text)) {
|
||||
for (const use of identifiers.original.get(name.text)!) {
|
||||
if (checker.getSymbolAtLocation(use) !== nameSymbol || use === name) {
|
||||
// This was a use of a different symbol with the same name, due to shadowing. Ignore.
|
||||
continue;
|
||||
@@ -468,7 +468,7 @@ namespace ts.codefix {
|
||||
getSynthesizedDeepClones(fn.typeParameters),
|
||||
getSynthesizedDeepClones(fn.parameters),
|
||||
getSynthesizedDeepClone(fn.type),
|
||||
convertToFunctionBody(getSynthesizedDeepClone(fn.body)));
|
||||
convertToFunctionBody(getSynthesizedDeepClone(fn.body!)));
|
||||
}
|
||||
|
||||
function classExpressionToDeclaration(name: string | undefined, additionalModifiers: ReadonlyArray<Modifier>, cls: ClassExpression): ClassDeclaration {
|
||||
|
||||
@@ -60,7 +60,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;
|
||||
const classDeclaration = symbol && symbol.declarations && find(symbol.declarations, isClassLike);
|
||||
if (!classDeclaration) return undefined;
|
||||
@@ -84,7 +84,7 @@ namespace ts.codefix {
|
||||
if (classDeclaration.kind === SyntaxKind.ClassExpression) {
|
||||
return;
|
||||
}
|
||||
const className = classDeclaration.name.getText();
|
||||
const className = classDeclaration.name!.getText();
|
||||
const staticInitialization = initializePropertyToUndefined(createIdentifier(className), tokenName);
|
||||
changeTracker.insertNodeAfter(classDeclarationSourceFile, classDeclaration, staticInitialization);
|
||||
}
|
||||
@@ -109,11 +109,11 @@ namespace ts.codefix {
|
||||
}
|
||||
|
||||
function getTypeNode(checker: TypeChecker, classDeclaration: ClassLikeDeclaration, token: Node) {
|
||||
let typeNode: TypeNode;
|
||||
let typeNode: TypeNode | undefined;
|
||||
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)));
|
||||
const widenedType = checker.getWidenedType(checker.getBaseTypeOfLiteralType(checker.getTypeAtLocation(otherExpression)!)); // TODO: GH#18217
|
||||
typeNode = checker.typeToTypeNode(widenedType, classDeclaration);
|
||||
}
|
||||
return typeNode || createKeywordTypeNode(SyntaxKind.AnyKeyword);
|
||||
|
||||
@@ -13,7 +13,7 @@ namespace ts.codefix {
|
||||
},
|
||||
fixIds: [fixId],
|
||||
getAllCodeActions: context => codeFixAll(context, errorCodes, (changes, diag) =>
|
||||
doChange(changes, context.sourceFile, getImportTypeNode(diag.file, diag.start!))),
|
||||
doChange(changes, context.sourceFile, getImportTypeNode(diag.file, diag.start))),
|
||||
});
|
||||
|
||||
function getImportTypeNode(sourceFile: SourceFile, pos: number): ImportTypeNode {
|
||||
|
||||
@@ -56,7 +56,7 @@ namespace ts.codefix {
|
||||
return;
|
||||
}
|
||||
|
||||
return {
|
||||
return insertBefore && {
|
||||
insertBefore,
|
||||
returnType: getReturnType(containingFunction)
|
||||
};
|
||||
@@ -65,7 +65,7 @@ namespace ts.codefix {
|
||||
function doChange(
|
||||
changes: textChanges.ChangeTracker,
|
||||
sourceFile: SourceFile,
|
||||
{ insertBefore, returnType }: { insertBefore: Node | undefined, returnType: TypeNode | undefined }): void {
|
||||
{ insertBefore, returnType }: { insertBefore: Node, returnType: TypeNode | undefined }): void {
|
||||
|
||||
if (returnType) {
|
||||
const entityName = getEntityNameFromTypeNode(returnType);
|
||||
|
||||
@@ -32,6 +32,6 @@ namespace ts.codefix {
|
||||
const { packageName } = getPackageName(moduleName);
|
||||
return diagCode === errorCodeCannotFindModule
|
||||
? (JsTyping.nodeCoreModules.has(packageName) ? "@types/node" : undefined)
|
||||
: (host.isKnownTypesPackageName(packageName) ? getTypesPackageName(packageName) : undefined);
|
||||
: (host.isKnownTypesPackageName!(packageName) ? getTypesPackageName(packageName) : undefined); // TODO: GH#18217
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,8 +33,8 @@ namespace ts.codefix {
|
||||
}
|
||||
|
||||
function addMissingMembers(classDeclaration: ClassLikeDeclaration, sourceFile: SourceFile, checker: TypeChecker, changeTracker: textChanges.ChangeTracker, preferences: UserPreferences): void {
|
||||
const extendsNode = getClassExtendsHeritageClauseElement(classDeclaration);
|
||||
const instantiatedExtendsType = checker.getTypeAtLocation(extendsNode);
|
||||
const extendsNode = getClassExtendsHeritageClauseElement(classDeclaration)!;
|
||||
const instantiatedExtendsType = checker.getTypeAtLocation(extendsNode)!;
|
||||
|
||||
// Note that this is ultimately derived from a map indexed by symbol names,
|
||||
// so duplicates cannot occur.
|
||||
@@ -46,7 +46,7 @@ namespace ts.codefix {
|
||||
function symbolPointsToNonPrivateAndAbstractMember(symbol: Symbol): boolean {
|
||||
// See `codeFixClassExtendAbstractProtectedProperty.ts` in https://github.com/Microsoft/TypeScript/pull/11547/files
|
||||
// (now named `codeFixClassExtendAbstractPrivateProperty.ts`)
|
||||
const flags = getModifierFlags(first(symbol.getDeclarations()));
|
||||
const flags = getModifierFlags(first(symbol.getDeclarations()!));
|
||||
return !(flags & ModifierFlags.Private) && !!(flags & ModifierFlags.Abstract);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ namespace ts.codefix {
|
||||
return codeFixAll(context, errorCodes, (changes, diag) => {
|
||||
const classDeclaration = getClass(diag.file, diag.start);
|
||||
if (addToSeen(seenClassDeclarations, getNodeId(classDeclaration))) {
|
||||
for (const implementedTypeNode of getClassImplementsHeritageClauseElements(classDeclaration)) {
|
||||
for (const implementedTypeNode of getClassImplementsHeritageClauseElements(classDeclaration)!) {
|
||||
addMissingDeclarations(context.program.getTypeChecker(), implementedTypeNode, diag.file, classDeclaration, changes, context.preferences);
|
||||
}
|
||||
}
|
||||
@@ -46,7 +46,7 @@ namespace ts.codefix {
|
||||
const implementedTypeSymbols = checker.getPropertiesOfType(implementedType);
|
||||
const nonPrivateMembers = implementedTypeSymbols.filter(symbol => !(getModifierFlags(symbol.valueDeclaration) & ModifierFlags.Private));
|
||||
|
||||
const classType = checker.getTypeAtLocation(classDeclaration);
|
||||
const classType = checker.getTypeAtLocation(classDeclaration)!;
|
||||
|
||||
if (!classType.getNumberIndexType()) {
|
||||
createMissingIndexSignatureDeclaration(implementedType, IndexKind.Number);
|
||||
@@ -60,7 +60,7 @@ namespace ts.codefix {
|
||||
function createMissingIndexSignatureDeclaration(type: InterfaceType, kind: IndexKind): void {
|
||||
const indexInfoOfKind = checker.getIndexInfoOfType(type, kind);
|
||||
if (indexInfoOfKind) {
|
||||
changeTracker.insertNodeAtClassStart(sourceFile, classDeclaration, checker.indexInfoToIndexSignatureDeclaration(indexInfoOfKind, kind, classDeclaration));
|
||||
changeTracker.insertNodeAtClassStart(sourceFile, classDeclaration, checker.indexInfoToIndexSignatureDeclaration(indexInfoOfKind, kind, classDeclaration)!);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,11 +32,11 @@ namespace ts.codefix {
|
||||
changes.deleteNode(sourceFile, superCall);
|
||||
}
|
||||
|
||||
function getNodes(sourceFile: SourceFile, pos: number): { readonly constructor: ConstructorDeclaration, readonly superCall: ExpressionStatement } {
|
||||
function getNodes(sourceFile: SourceFile, pos: number): { readonly constructor: ConstructorDeclaration, readonly superCall: ExpressionStatement } | undefined {
|
||||
const token = getTokenAtPosition(sourceFile, pos, /*includeJsDocComment*/ false);
|
||||
if (token.kind !== SyntaxKind.ThisKeyword) return undefined;
|
||||
const constructor = getContainingFunction(token) as ConstructorDeclaration;
|
||||
const superCall = findSuperCall(constructor.body);
|
||||
const superCall = findSuperCall(constructor.body!);
|
||||
// figure out if the `this` access is actually inside the supercall
|
||||
// i.e. super(this.a), since in that case we won't suggest a fix
|
||||
return superCall && !superCall.expression.arguments.some(arg => isPropertyAccessExpression(arg) && arg.expression === token) ? { constructor, superCall } : undefined;
|
||||
|
||||
@@ -21,8 +21,8 @@ namespace ts.codefix {
|
||||
|
||||
function getNodes(sourceFile: SourceFile, pos: number) {
|
||||
const token = getTokenAtPosition(sourceFile, pos, /*includeJsDocComment*/ false);
|
||||
const heritageClauses = getContainingClass(token)!.heritageClauses;
|
||||
const extendsToken = heritageClauses[0].getFirstToken();
|
||||
const heritageClauses = getContainingClass(token)!.heritageClauses!;
|
||||
const extendsToken = heritageClauses[0].getFirstToken()!;
|
||||
return extendsToken.kind === SyntaxKind.ExtendsKeyword ? { extendsToken, heritageClauses } : undefined;
|
||||
}
|
||||
|
||||
|
||||
@@ -19,7 +19,8 @@ namespace ts.codefix {
|
||||
},
|
||||
fixIds: [fixId],
|
||||
getAllCodeActions: context => codeFixAll(context, errorCodes, (changes, diag) => {
|
||||
doChange(changes, context.sourceFile, getInfo(diag.file, diag.start, diag.code));
|
||||
const info = getInfo(diag.file, diag.start, diag.code);
|
||||
if (info) doChange(changes, context.sourceFile, info);
|
||||
}),
|
||||
});
|
||||
|
||||
@@ -27,7 +28,7 @@ namespace ts.codefix {
|
||||
function getInfo(sourceFile: SourceFile, pos: number, diagCode: number): Info | undefined {
|
||||
const node = getTokenAtPosition(sourceFile, pos, /*includeJsDocComment*/ false);
|
||||
if (!isIdentifier(node)) return undefined;
|
||||
return { node, className: diagCode === didYouMeanStaticMemberCode ? getContainingClass(node).name.text : undefined };
|
||||
return { node, className: diagCode === didYouMeanStaticMemberCode ? getContainingClass(node)!.name!.text : undefined };
|
||||
}
|
||||
|
||||
function doChange(changes: textChanges.ChangeTracker, sourceFile: SourceFile, { node, className }: Info): void {
|
||||
|
||||
@@ -64,12 +64,12 @@ namespace ts.codefix {
|
||||
return [];
|
||||
}
|
||||
const expr = node.expression;
|
||||
const type = context.program.getTypeChecker().getTypeAtLocation(expr);
|
||||
const type = context.program.getTypeChecker().getTypeAtLocation(expr)!; // TODO: GH#18217
|
||||
if (!(type.symbol && (type.symbol as TransientSymbol).originatingImport)) {
|
||||
return [];
|
||||
}
|
||||
const fixes: CodeFixAction[] = [];
|
||||
const relatedImport = (type.symbol as TransientSymbol).originatingImport;
|
||||
const relatedImport = (type.symbol as TransientSymbol).originatingImport!; // TODO: GH#18217
|
||||
if (!isImportCall(relatedImport)) {
|
||||
addRange(fixes, getCodeFixesForImportDeclaration(context, relatedImport));
|
||||
}
|
||||
|
||||
@@ -30,7 +30,7 @@ namespace ts.codefix {
|
||||
const { fixId, program, sourceFile } = context;
|
||||
const checker = program.getTypeChecker();
|
||||
return codeFixAll(context, errorCodes, (changes, err) => {
|
||||
const info = getInfo(err.file, err.start!, checker);
|
||||
const info = getInfo(err.file, err.start, checker);
|
||||
if (!info) return;
|
||||
const { typeNode, type } = info;
|
||||
const fixedType = typeNode.kind === SyntaxKind.JSDocNullableType && fixId === fixIdNullable ? checker.getNullableType(type, TypeFlags.Undefined) : type;
|
||||
@@ -40,10 +40,10 @@ namespace ts.codefix {
|
||||
});
|
||||
|
||||
function doChange(changes: textChanges.ChangeTracker, sourceFile: SourceFile, oldTypeNode: TypeNode, newType: Type, checker: TypeChecker): void {
|
||||
changes.replaceNode(sourceFile, oldTypeNode, checker.typeToTypeNode(newType, /*enclosingDeclaration*/ oldTypeNode));
|
||||
changes.replaceNode(sourceFile, oldTypeNode, checker.typeToTypeNode(newType, /*enclosingDeclaration*/ oldTypeNode)!); // TODO: GH#18217
|
||||
}
|
||||
|
||||
function getInfo(sourceFile: SourceFile, pos: number, checker: TypeChecker): { readonly typeNode: TypeNode, type: Type } {
|
||||
function getInfo(sourceFile: SourceFile, pos: number, checker: TypeChecker): { readonly typeNode: TypeNode, readonly type: Type } | undefined {
|
||||
const decl = findAncestor(getTokenAtPosition(sourceFile, pos, /*includeJsDocComment*/ false), isTypeContainer);
|
||||
const typeNode = decl && decl.type;
|
||||
return typeNode && { typeNode, type: checker.getTypeFromTypeNode(typeNode) };
|
||||
|
||||
@@ -14,14 +14,14 @@ namespace ts.codefix {
|
||||
if (!info) return undefined;
|
||||
const { node, suggestion } = info;
|
||||
const { target } = context.host.getCompilationSettings();
|
||||
const changes = textChanges.ChangeTracker.with(context, t => doChange(t, sourceFile, node, suggestion, target));
|
||||
const changes = textChanges.ChangeTracker.with(context, t => doChange(t, sourceFile, node, suggestion, target!));
|
||||
return [createCodeFixAction("spelling", changes, [Diagnostics.Change_spelling_to_0, suggestion], fixId, Diagnostics.Fix_all_detected_spelling_errors)];
|
||||
},
|
||||
fixIds: [fixId],
|
||||
getAllCodeActions: context => codeFixAll(context, errorCodes, (changes, diag) => {
|
||||
const info = getInfo(diag.file, diag.start, context);
|
||||
const { target } = context.host.getCompilationSettings();
|
||||
if (info) doChange(changes, context.sourceFile, info.node, info.suggestion, target);
|
||||
if (info) doChange(changes, context.sourceFile, info.node, info.suggestion, target!);
|
||||
}),
|
||||
});
|
||||
|
||||
@@ -32,15 +32,15 @@ namespace ts.codefix {
|
||||
const node = getTokenAtPosition(sourceFile, pos, /*includeJsDocComment*/ false); // TODO: GH#15852
|
||||
const checker = context.program.getTypeChecker();
|
||||
|
||||
let suggestion: string;
|
||||
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) {
|
||||
Debug.assert(node.kind === SyntaxKind.Identifier);
|
||||
const importDeclaration = findAncestor(node, isImportDeclaration);
|
||||
const importDeclaration = findAncestor(node, isImportDeclaration)!;
|
||||
const resolvedSourceFile = getResolvedSourceFileFromImportDeclaration(sourceFile, context, importDeclaration);
|
||||
if (resolvedSourceFile && resolvedSourceFile.symbol) {
|
||||
suggestion = checker.getSuggestionForNonexistentModule(node as Identifier, resolvedSourceFile.symbol);
|
||||
|
||||
@@ -77,8 +77,9 @@ namespace ts.codefix {
|
||||
|
||||
function addUndefinedType(changeTracker: textChanges.ChangeTracker, propertyDeclarationSourceFile: SourceFile, propertyDeclaration: PropertyDeclaration): void {
|
||||
const undefinedTypeNode = createKeywordTypeNode(SyntaxKind.UndefinedKeyword);
|
||||
const types = isUnionTypeNode(propertyDeclaration.type) ? propertyDeclaration.type.types.concat(undefinedTypeNode) : [propertyDeclaration.type, undefinedTypeNode];
|
||||
changeTracker.replaceNode(propertyDeclarationSourceFile, propertyDeclaration.type, createUnionTypeNode(types));
|
||||
const type = propertyDeclaration.type!; // TODO: GH#18217
|
||||
const types = isUnionTypeNode(type) ? type.types.concat(undefinedTypeNode) : [type, undefinedTypeNode];
|
||||
changeTracker.replaceNode(propertyDeclarationSourceFile, type, createUnionTypeNode(types));
|
||||
}
|
||||
|
||||
function getActionForAddMissingInitializer(context: CodeFixContext, propertyDeclaration: PropertyDeclaration): CodeFixAction | undefined {
|
||||
@@ -104,7 +105,7 @@ namespace ts.codefix {
|
||||
}
|
||||
|
||||
function getInitializer(checker: TypeChecker, propertyDeclaration: PropertyDeclaration): Expression | undefined {
|
||||
return getDefaultValueFromType(checker, checker.getTypeFromTypeNode(propertyDeclaration.type));
|
||||
return getDefaultValueFromType(checker, checker.getTypeFromTypeNode(propertyDeclaration.type!)); // TODO: GH#18217
|
||||
}
|
||||
|
||||
function getDefaultValueFromType (checker: TypeChecker, type: Type): Expression | undefined {
|
||||
|
||||
@@ -14,7 +14,7 @@ namespace ts.codefix {
|
||||
|
||||
function doChange(changes: textChanges.ChangeTracker, sourceFile: SourceFile, start: number): void {
|
||||
const token = getTokenAtPosition(sourceFile, start, /*includeJsDocComment*/ false);
|
||||
const statement = findAncestor(token, isStatement);
|
||||
const statement = findAncestor(token, isStatement)!;
|
||||
Debug.assert(statement.getStart(sourceFile) === token.getStart(sourceFile));
|
||||
|
||||
const container = (isBlock(statement.parent) ? statement.parent : statement).parent;
|
||||
@@ -60,6 +60,8 @@ namespace ts.codefix {
|
||||
return getModuleInstanceState(s as ModuleDeclaration) !== ModuleInstanceState.Instantiated;
|
||||
case SyntaxKind.EnumDeclaration:
|
||||
return hasModifier(s, ModifierFlags.Const);
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -53,7 +53,7 @@ namespace ts.codefix {
|
||||
return codeFixAll(context, errorCodes, (changes, diag) => {
|
||||
const { sourceFile } = context;
|
||||
const startToken = getTokenAtPosition(sourceFile, diag.start, /*includeJsDocComment*/ false);
|
||||
const token = findPrecedingToken(textSpanEnd(diag), diag.file);
|
||||
const token = findPrecedingToken(textSpanEnd(diag), diag.file)!;
|
||||
switch (context.fixId) {
|
||||
case fixIdPrefix:
|
||||
if (isIdentifier(token) && canPrefix(token)) {
|
||||
@@ -116,9 +116,9 @@ namespace ts.codefix {
|
||||
}
|
||||
|
||||
function getToken(sourceFile: SourceFile, pos: number): Node {
|
||||
const token = findPrecedingToken(pos, sourceFile, /*startNode*/ undefined, /*includeJsDoc*/ true);
|
||||
const token = findPrecedingToken(pos, sourceFile, /*startNode*/ undefined, /*includeJsDoc*/ true)!;
|
||||
// this handles var ["computed"] = 12;
|
||||
return token.kind === SyntaxKind.CloseBracketToken ? findPrecedingToken(pos - 1, sourceFile) : token;
|
||||
return token.kind === SyntaxKind.CloseBracketToken ? findPrecedingToken(pos - 1, sourceFile)! : token;
|
||||
}
|
||||
|
||||
function tryPrefixDeclaration(changes: textChanges.ChangeTracker, errorCode: number, sourceFile: SourceFile, token: Node): void {
|
||||
@@ -208,7 +208,7 @@ namespace ts.codefix {
|
||||
oldFunction,
|
||||
oldFunction.modifiers,
|
||||
oldFunction.typeParameters,
|
||||
/*parameters*/ undefined,
|
||||
/*parameters*/ undefined!, // TODO: GH#18217
|
||||
oldFunction.type,
|
||||
oldFunction.equalsGreaterThanToken,
|
||||
oldFunction.body);
|
||||
@@ -242,7 +242,7 @@ namespace ts.codefix {
|
||||
|
||||
// handle case where 'import a = A;'
|
||||
case SyntaxKind.ImportEqualsDeclaration:
|
||||
const importEquals = getAncestor(identifier, SyntaxKind.ImportEqualsDeclaration);
|
||||
const importEquals = getAncestor(identifier, SyntaxKind.ImportEqualsDeclaration)!;
|
||||
changes.deleteNode(sourceFile, importEquals);
|
||||
break;
|
||||
|
||||
@@ -264,15 +264,15 @@ namespace ts.codefix {
|
||||
}
|
||||
else {
|
||||
// import |d,| * as ns from './file'
|
||||
const start = importClause.name.getStart(sourceFile);
|
||||
const nextToken = getTokenAtPosition(sourceFile, importClause.name.end, /*includeJsDocComment*/ false);
|
||||
const start = importClause.name!.getStart(sourceFile);
|
||||
const nextToken = getTokenAtPosition(sourceFile, importClause.name!.end, /*includeJsDocComment*/ false);
|
||||
if (nextToken && nextToken.kind === SyntaxKind.CommaToken) {
|
||||
// shift first non-whitespace position after comma to the start position of the node
|
||||
const end = skipTrivia(sourceFile.text, nextToken.end, /*stopAfterLineBreaks*/ false, /*stopAtComments*/ true);
|
||||
changes.deleteRange(sourceFile, { pos: start, end });
|
||||
}
|
||||
else {
|
||||
changes.deleteNode(sourceFile, importClause.name);
|
||||
changes.deleteNode(sourceFile, importClause.name!);
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -301,7 +301,7 @@ namespace ts.codefix {
|
||||
// Delete the entire import declaration
|
||||
// |import * as ns from './file'|
|
||||
// |import { a } from './file'|
|
||||
const importDecl = getAncestor(namedBindings, SyntaxKind.ImportDeclaration);
|
||||
const importDecl = getAncestor(namedBindings, SyntaxKind.ImportDeclaration)!;
|
||||
changes.deleteNode(sourceFile, importDecl);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ namespace ts.codefix {
|
||||
* @returns Empty string iff there are no member insertions.
|
||||
*/
|
||||
export function createMissingMemberNodes(classDeclaration: ClassLikeDeclaration, possiblyMissingSymbols: ReadonlyArray<Symbol>, checker: TypeChecker, preferences: UserPreferences, out: (node: ClassElement) => void): void {
|
||||
const classMembers = classDeclaration.symbol.members;
|
||||
const classMembers = classDeclaration.symbol.members!;
|
||||
for (const symbol of possiblyMissingSymbols) {
|
||||
if (!classMembers.has(symbol.escapedName)) {
|
||||
addNewNodeForMemberSymbol(symbol, classDeclaration, checker, preferences, out);
|
||||
@@ -72,7 +72,7 @@ namespace ts.codefix {
|
||||
}
|
||||
|
||||
if (declarations.length > signatures.length) {
|
||||
const signature = checker.getSignatureFromDeclaration(declarations[declarations.length - 1] as SignatureDeclaration);
|
||||
const signature = checker.getSignatureFromDeclaration(declarations[declarations.length - 1] as SignatureDeclaration)!;
|
||||
outputMethod(signature, modifiers, name, createStubbedMethodBody(preferences));
|
||||
}
|
||||
else {
|
||||
@@ -82,13 +82,21 @@ namespace ts.codefix {
|
||||
break;
|
||||
}
|
||||
|
||||
function outputMethod(signature: Signature, modifiers: NodeArray<Modifier>, name: PropertyName, body?: Block): void {
|
||||
function outputMethod(signature: Signature, modifiers: NodeArray<Modifier> | undefined, name: PropertyName, body?: Block): void {
|
||||
const method = signatureToMethodDeclaration(checker, signature, enclosingDeclaration, modifiers, name, optional, body);
|
||||
if (method) out(method);
|
||||
}
|
||||
}
|
||||
|
||||
function signatureToMethodDeclaration(checker: TypeChecker, signature: Signature, enclosingDeclaration: ClassLikeDeclaration, modifiers: NodeArray<Modifier>, name: PropertyName, optional: boolean, body: Block | undefined) {
|
||||
function signatureToMethodDeclaration(
|
||||
checker: TypeChecker,
|
||||
signature: Signature,
|
||||
enclosingDeclaration: ClassLikeDeclaration,
|
||||
modifiers: NodeArray<Modifier> | undefined,
|
||||
name: PropertyName,
|
||||
optional: boolean,
|
||||
body: Block | undefined,
|
||||
): MethodDeclaration | undefined {
|
||||
const signatureDeclaration = <MethodDeclaration>checker.signatureToSignatureDeclaration(signature, SyntaxKind.MethodDeclaration, enclosingDeclaration, NodeBuilderFlags.SuppressAnyReturnType);
|
||||
if (!signatureDeclaration) {
|
||||
return undefined;
|
||||
@@ -116,7 +124,7 @@ namespace ts.codefix {
|
||||
methodName,
|
||||
/*questionToken*/ undefined,
|
||||
/*typeParameters*/ inJs ? undefined : map(typeArguments, (_, i) =>
|
||||
createTypeParameterDeclaration(CharacterCodes.T + typeArguments.length - 1 <= CharacterCodes.Z ? String.fromCharCode(CharacterCodes.T + i) : `T${i}`)),
|
||||
createTypeParameterDeclaration(CharacterCodes.T + typeArguments!.length - 1 <= CharacterCodes.Z ? String.fromCharCode(CharacterCodes.T + i) : `T${i}`)),
|
||||
/*parameters*/ createDummyParameters(args.length, /*names*/ undefined, /*minArgumentCount*/ undefined, inJs),
|
||||
/*type*/ inJs ? undefined : createKeywordTypeNode(SyntaxKind.AnyKeyword),
|
||||
createStubbedMethodBody(preferences));
|
||||
@@ -190,7 +198,7 @@ namespace ts.codefix {
|
||||
}
|
||||
|
||||
function createStubbedMethod(
|
||||
modifiers: ReadonlyArray<Modifier>,
|
||||
modifiers: ReadonlyArray<Modifier> | undefined,
|
||||
name: PropertyName,
|
||||
optional: boolean,
|
||||
typeParameters: ReadonlyArray<TypeParameterDeclaration> | undefined,
|
||||
|
||||
@@ -25,7 +25,7 @@ namespace ts.codefix {
|
||||
}
|
||||
|
||||
interface ImportCodeFixContext extends SymbolContext {
|
||||
symbolToken: Node;
|
||||
symbolToken: Node | undefined;
|
||||
program: Program;
|
||||
checker: TypeChecker;
|
||||
compilerOptions: CompilerOptions;
|
||||
@@ -148,8 +148,8 @@ namespace ts.codefix {
|
||||
for (const { declaration } of existingImports) {
|
||||
const namespace = getNamespaceImportName(declaration);
|
||||
if (namespace) {
|
||||
const moduleSymbol = context.checker.getAliasedSymbol(context.checker.getSymbolAtLocation(namespace));
|
||||
if (moduleSymbol && moduleSymbol.exports.has(escapeLeadingUnderscores(context.symbolName))) {
|
||||
const moduleSymbol = context.checker.getAliasedSymbol(context.checker.getSymbolAtLocation(namespace)!);
|
||||
if (moduleSymbol && moduleSymbol.exports!.has(escapeLeadingUnderscores(context.symbolName))) {
|
||||
useExisting.push(getCodeActionForUseExistingNamespaceImport(namespace.text, context, context.symbolToken));
|
||||
}
|
||||
}
|
||||
@@ -263,7 +263,7 @@ namespace ts.codefix {
|
||||
): void {
|
||||
const fromExistingImport = firstDefined(existingImports, ({ declaration, importKind }) => {
|
||||
if (declaration.kind === SyntaxKind.ImportDeclaration && declaration.importClause) {
|
||||
const changes = tryUpdateExistingImport(ctx, isImportClause(declaration.importClause) && declaration.importClause || undefined, importKind);
|
||||
const changes = tryUpdateExistingImport(ctx, (isImportClause(declaration.importClause) && declaration.importClause || undefined)!, importKind); // TODO: GH#18217
|
||||
if (changes) {
|
||||
const moduleSpecifierWithoutQuotes = stripQuotes(declaration.moduleSpecifier.getText());
|
||||
return createCodeAction(Diagnostics.Add_0_to_existing_import_declaration_from_1, [ctx.symbolName, moduleSpecifierWithoutQuotes], changes);
|
||||
@@ -296,7 +296,7 @@ namespace ts.codefix {
|
||||
function tryUpdateExistingImport(context: SymbolContext, importClause: ImportClause | ImportEqualsDeclaration, importKind: ImportKind): FileTextChanges[] | undefined {
|
||||
const { symbolName, sourceFile } = context;
|
||||
const { name } = importClause;
|
||||
const { namedBindings } = importClause.kind !== SyntaxKind.ImportEqualsDeclaration && importClause;
|
||||
const { namedBindings } = (importClause.kind !== SyntaxKind.ImportEqualsDeclaration && importClause) as ImportClause; // TODO: GH#18217
|
||||
switch (importKind) {
|
||||
case ImportKind.Default:
|
||||
return name ? undefined : ChangeTracker.with(context, t =>
|
||||
@@ -348,13 +348,13 @@ namespace ts.codefix {
|
||||
return createCodeAction(Diagnostics.Change_0_to_1, [symbolName, `${namespacePrefix}.${symbolName}`], changes);
|
||||
}
|
||||
|
||||
function getImportCodeActions(context: CodeFixContext): CodeFixAction[] {
|
||||
function getImportCodeActions(context: CodeFixContext): CodeFixAction[] | undefined {
|
||||
return context.errorCode === Diagnostics._0_refers_to_a_UMD_global_but_the_current_file_is_a_module_Consider_adding_an_import_instead.code
|
||||
? getActionsForUMDImport(context)
|
||||
: getActionsForNonUMDImport(context);
|
||||
}
|
||||
|
||||
function getActionsForUMDImport(context: CodeFixContext): CodeFixAction[] {
|
||||
function getActionsForUMDImport(context: CodeFixContext): CodeFixAction[] | undefined {
|
||||
const token = getTokenAtPosition(context.sourceFile, context.span.start, /*includeJsDocComment*/ false);
|
||||
const checker = context.program.getTypeChecker();
|
||||
|
||||
@@ -376,10 +376,10 @@ namespace ts.codefix {
|
||||
}
|
||||
|
||||
if (isUMDExportSymbol(umdSymbol)) {
|
||||
const symbol = checker.getAliasedSymbol(umdSymbol);
|
||||
const symbol = checker.getAliasedSymbol(umdSymbol!);
|
||||
if (symbol) {
|
||||
return getCodeActionsForImport([{ moduleSymbol: symbol, importKind: getUmdImportKind(context.program.getCompilerOptions()) }],
|
||||
convertToImportCodeFixContext(context, token, umdSymbol.name));
|
||||
convertToImportCodeFixContext(context, token, umdSymbol!.name));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -443,7 +443,7 @@ namespace ts.codefix {
|
||||
if ((
|
||||
localSymbol && localSymbol.escapedName === symbolName ||
|
||||
getEscapedNameForExportDefault(defaultExport) === symbolName ||
|
||||
moduleSymbolToValidIdentifier(moduleSymbol, program.getCompilerOptions().target) === symbolName
|
||||
moduleSymbolToValidIdentifier(moduleSymbol, program.getCompilerOptions().target!) === symbolName
|
||||
) && checkSymbolHasMeaning(localSymbol || defaultExport, currentTokenMeaning)) {
|
||||
addSymbol(moduleSymbol, localSymbol || defaultExport, ImportKind.Default);
|
||||
}
|
||||
@@ -456,7 +456,7 @@ namespace ts.codefix {
|
||||
}
|
||||
|
||||
function getEscapedNameForExportDefault(symbol: Symbol): __String | undefined {
|
||||
return firstDefined(symbol.declarations, declaration => {
|
||||
return symbol.declarations && firstDefined(symbol.declarations, declaration => {
|
||||
if (isExportAssignment(declaration)) {
|
||||
if (isIdentifier(declaration.expression)) {
|
||||
return declaration.expression.escapedText;
|
||||
|
||||
@@ -31,17 +31,17 @@ namespace ts.codefix {
|
||||
}
|
||||
|
||||
const token = getTokenAtPosition(sourceFile, start, /*includeJsDocComment*/ false);
|
||||
let declaration!: Declaration;
|
||||
let declaration!: Declaration | undefined;
|
||||
const changes = textChanges.ChangeTracker.with(context, changes => { declaration = doChange(changes, sourceFile, token, errorCode, program, cancellationToken, /*markSeenseen*/ returnTrue); });
|
||||
return changes.length === 0 ? undefined
|
||||
: [createCodeFixAction(fixId, changes, [getDiagnostic(errorCode, token), getNameOfDeclaration(declaration).getText(sourceFile)], fixId, Diagnostics.Infer_all_types_from_usage)];
|
||||
: [createCodeFixAction(fixId, changes, [getDiagnostic(errorCode, token), getNameOfDeclaration(declaration!).getText(sourceFile)], fixId, Diagnostics.Infer_all_types_from_usage)];
|
||||
},
|
||||
fixIds: [fixId],
|
||||
getAllCodeActions(context) {
|
||||
const { sourceFile, program, cancellationToken } = context;
|
||||
const markSeen = nodeSeenTracker();
|
||||
return codeFixAll(context, errorCodes, (changes, err) => {
|
||||
doChange(changes, sourceFile, getTokenAtPosition(err.file!, err.start!, /*includeJsDocComment*/ false), err.code, program, cancellationToken, markSeen);
|
||||
doChange(changes, sourceFile, getTokenAtPosition(err.file, err.start, /*includeJsDocComment*/ false), err.code, program, cancellationToken, markSeen);
|
||||
});
|
||||
},
|
||||
});
|
||||
@@ -49,7 +49,7 @@ namespace ts.codefix {
|
||||
function getDiagnostic(errorCode: number, token: Node): DiagnosticMessage {
|
||||
switch (errorCode) {
|
||||
case Diagnostics.Parameter_0_implicitly_has_an_1_type.code:
|
||||
return isSetAccessor(getContainingFunction(token)) ? Diagnostics.Infer_type_of_0_from_usage : Diagnostics.Infer_parameter_types_from_usage;
|
||||
return isSetAccessor(getContainingFunction(token)!) ? Diagnostics.Infer_type_of_0_from_usage : Diagnostics.Infer_parameter_types_from_usage; // TODO: GH#18217
|
||||
case Diagnostics.Rest_parameter_0_implicitly_has_an_any_type.code:
|
||||
return Diagnostics.Infer_parameter_types_from_usage;
|
||||
default:
|
||||
@@ -182,7 +182,8 @@ namespace ts.codefix {
|
||||
const notAccessible = () => { typeIsAccessible = false; };
|
||||
const res = checker.typeToTypeNode(type, enclosingScope, /*flags*/ undefined, {
|
||||
trackSymbol: (symbol, declaration, meaning) => {
|
||||
typeIsAccessible = typeIsAccessible && checker.isSymbolAccessible(symbol, declaration, meaning, /*shouldComputeAliasToMarkVisible*/ false).accessibility === SymbolAccessibility.Accessible;
|
||||
// TODO: GH#18217
|
||||
typeIsAccessible = typeIsAccessible && checker.isSymbolAccessible(symbol, declaration, meaning!, /*shouldComputeAliasToMarkVisible*/ false).accessibility === SymbolAccessibility.Accessible;
|
||||
},
|
||||
reportInaccessibleThisError: notAccessible,
|
||||
reportPrivateInBaseOfClassExpression: notAccessible,
|
||||
@@ -399,7 +400,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);
|
||||
}
|
||||
@@ -410,7 +411,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);
|
||||
}
|
||||
@@ -470,7 +471,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)!);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -499,7 +500,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) {
|
||||
@@ -525,19 +526,19 @@ namespace ts.codefix {
|
||||
return checker.getWidenedType(checker.getUnionType(usageContext.candidateTypes.map(t => checker.getBaseTypeOfLiteralType(t)), UnionReduction.Subtype));
|
||||
}
|
||||
else if (usageContext.properties && hasCallContext(usageContext.properties.get("then" as __String))) {
|
||||
const paramType = getParameterTypeFromCallContexts(0, usageContext.properties.get("then" as __String).callContexts, /*isRestParameter*/ false, checker);
|
||||
const paramType = getParameterTypeFromCallContexts(0, usageContext.properties.get("then" as __String)!.callContexts!, /*isRestParameter*/ false, checker)!; // TODO: GH#18217
|
||||
const types = paramType.getCallSignatures().map(c => c.getReturnType());
|
||||
return checker.createPromiseType(types.length ? checker.getUnionType(types, UnionReduction.Subtype) : checker.getAnyType());
|
||||
}
|
||||
else if (usageContext.properties && hasCallContext(usageContext.properties.get("push" as __String))) {
|
||||
return checker.createArrayType(getParameterTypeFromCallContexts(0, usageContext.properties.get("push" as __String).callContexts, /*isRestParameter*/ false, checker));
|
||||
return checker.createArrayType(getParameterTypeFromCallContexts(0, usageContext.properties.get("push" as __String)!.callContexts!, /*isRestParameter*/ false, checker)!);
|
||||
}
|
||||
else if (usageContext.properties || usageContext.callContexts || usageContext.constructContexts || usageContext.numberIndexContext || usageContext.stringIndexContext) {
|
||||
const members = createUnderscoreEscapedMap<Symbol>();
|
||||
const callSignatures: Signature[] = [];
|
||||
const constructSignatures: Signature[] = [];
|
||||
let stringIndexInfo: IndexInfo;
|
||||
let numberIndexInfo: IndexInfo;
|
||||
let stringIndexInfo: IndexInfo | undefined;
|
||||
let numberIndexInfo: IndexInfo | undefined;
|
||||
|
||||
if (usageContext.properties) {
|
||||
usageContext.properties.forEach((context, name) => {
|
||||
@@ -560,14 +561,14 @@ namespace ts.codefix {
|
||||
}
|
||||
|
||||
if (usageContext.numberIndexContext) {
|
||||
numberIndexInfo = checker.createIndexInfo(getTypeFromUsageContext(usageContext.numberIndexContext, checker), /*isReadonly*/ false);
|
||||
numberIndexInfo = checker.createIndexInfo(getTypeFromUsageContext(usageContext.numberIndexContext, checker)!, /*isReadonly*/ false); // TODO: GH#18217
|
||||
}
|
||||
|
||||
if (usageContext.stringIndexContext) {
|
||||
stringIndexInfo = checker.createIndexInfo(getTypeFromUsageContext(usageContext.stringIndexContext, checker), /*isReadonly*/ false);
|
||||
stringIndexInfo = checker.createIndexInfo(getTypeFromUsageContext(usageContext.stringIndexContext, checker)!, /*isReadonly*/ false);
|
||||
}
|
||||
|
||||
return checker.createAnonymousType(/*symbol*/ undefined, members, callSignatures, constructSignatures, stringIndexInfo, numberIndexInfo);
|
||||
return checker.createAnonymousType(/*symbol*/ undefined!, members, callSignatures, constructSignatures, stringIndexInfo, numberIndexInfo); // TODO: GH#18217
|
||||
}
|
||||
else {
|
||||
return undefined;
|
||||
@@ -604,17 +605,18 @@ namespace ts.codefix {
|
||||
parameters.push(symbol);
|
||||
}
|
||||
const returnType = getTypeFromUsageContext(callContext.returnType, checker) || checker.getVoidType();
|
||||
return checker.createSignature(/*declaration*/ undefined, /*typeParameters*/ undefined, /*thisParameter*/ undefined, parameters, returnType, /*typePredicate*/ undefined, callContext.argumentTypes.length, /*hasRestParameter*/ false, /*hasLiteralTypes*/ false);
|
||||
// TODO: GH#18217
|
||||
return checker.createSignature(/*declaration*/ undefined!, /*typeParameters*/ undefined, /*thisParameter*/ undefined, parameters, returnType, /*typePredicate*/ undefined, callContext.argumentTypes.length, /*hasRestParameter*/ false, /*hasLiteralTypes*/ false);
|
||||
}
|
||||
|
||||
function addCandidateType(context: UsageContext, type: Type) {
|
||||
function addCandidateType(context: UsageContext, type: Type | undefined) {
|
||||
if (type && !(type.flags & TypeFlags.Any) && !(type.flags & TypeFlags.Never)) {
|
||||
(context.candidateTypes || (context.candidateTypes = [])).push(type);
|
||||
}
|
||||
}
|
||||
|
||||
function hasCallContext(usageContext: UsageContext) {
|
||||
return usageContext && usageContext.callContexts;
|
||||
function hasCallContext(usageContext: UsageContext | undefined): boolean {
|
||||
return !!usageContext && !!usageContext.callContexts;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -182,7 +182,7 @@ namespace ts.moduleSpecifiers {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const parts = getNodeModulePathParts(moduleFileName);
|
||||
const parts: NodeModulePathParts = getNodeModulePathParts(moduleFileName)!;
|
||||
|
||||
if (!parts) {
|
||||
return undefined;
|
||||
@@ -201,8 +201,8 @@ namespace ts.moduleSpecifiers {
|
||||
// If the file is the main module, it can be imported by the package name
|
||||
const packageRootPath = path.substring(0, parts.packageRootIndex);
|
||||
const packageJsonPath = combinePaths(packageRootPath, "package.json");
|
||||
if (host.fileExists(packageJsonPath)) {
|
||||
const packageJsonContent = JSON.parse(host.readFile(packageJsonPath));
|
||||
if (host.fileExists!(packageJsonPath)) { // TODO: GH#18217
|
||||
const packageJsonContent = JSON.parse(host.readFile!(packageJsonPath)!);
|
||||
if (packageJsonContent) {
|
||||
const mainFileRelative = packageJsonContent.typings || packageJsonContent.types || packageJsonContent.main;
|
||||
if (mainFileRelative) {
|
||||
@@ -237,7 +237,13 @@ namespace ts.moduleSpecifiers {
|
||||
}
|
||||
}
|
||||
|
||||
function getNodeModulePathParts(fullPath: string) {
|
||||
interface NodeModulePathParts {
|
||||
readonly topLevelNodeModulesIndex: number;
|
||||
readonly topLevelPackageNameIndex: number;
|
||||
readonly packageRootIndex: number;
|
||||
readonly fileNameIndex: number;
|
||||
}
|
||||
function getNodeModulePathParts(fullPath: string): NodeModulePathParts | undefined {
|
||||
// If fullPath can't be valid module file within node_modules, returns undefined.
|
||||
// Example of expected pattern: /base/path/node_modules/[@scope/otherpackage/@otherscope/node_modules/]package/[subdirectory/]file.js
|
||||
// Returns indices: ^ ^ ^ ^
|
||||
@@ -297,7 +303,7 @@ namespace ts.moduleSpecifiers {
|
||||
|
||||
function getPathRelativeToRootDirs(path: string, rootDirs: ReadonlyArray<string>, getCanonicalFileName: GetCanonicalFileName): string | undefined {
|
||||
return firstDefined(rootDirs, rootDir => {
|
||||
const relativePath = getRelativePathIfInDirectory(path, rootDir, getCanonicalFileName);
|
||||
const relativePath = getRelativePathIfInDirectory(path, rootDir, getCanonicalFileName)!; // TODO: GH#18217
|
||||
return isPathRelativeToParent(relativePath) ? undefined : relativePath;
|
||||
});
|
||||
}
|
||||
|
||||
+69
-64
@@ -34,7 +34,7 @@ namespace ts.Completions {
|
||||
}
|
||||
|
||||
const contextToken = findPrecedingToken(position, sourceFile);
|
||||
if (triggerCharacter && !isValidTrigger(sourceFile, triggerCharacter, contextToken, position)) return undefined;
|
||||
if (triggerCharacter && !isValidTrigger(sourceFile, triggerCharacter, contextToken!, position)) return undefined; // TODO: GH#18217
|
||||
|
||||
if (isInString(sourceFile, position, contextToken)) {
|
||||
return !contextToken || !isStringLiteralLike(contextToken)
|
||||
@@ -100,7 +100,7 @@ namespace ts.Completions {
|
||||
return { isGlobalCompletion: false, isMemberCompletion: false, isNewIdentifierLocation: false, entries };
|
||||
}
|
||||
|
||||
function completionInfoFromData(sourceFile: SourceFile, typeChecker: TypeChecker, compilerOptions: CompilerOptions, log: Log, completionData: CompletionData, preferences: UserPreferences): CompletionInfo {
|
||||
function completionInfoFromData(sourceFile: SourceFile, typeChecker: TypeChecker, compilerOptions: CompilerOptions, log: Log, completionData: CompletionData, preferences: UserPreferences): CompletionInfo | undefined {
|
||||
const { symbols, completionKind, isInSnippetScope, isNewIdentifierLocation, location, propertyAccessToConvert, keywordFilters, symbolToOriginInfoMap, recommendedCompletion, isJsxInitializer } = completionData;
|
||||
|
||||
if (sourceFile.languageVariant === LanguageVariant.JSX && location && location.parent && isJsxClosingElement(location.parent)) {
|
||||
@@ -122,15 +122,15 @@ namespace ts.Completions {
|
||||
const entries: CompletionEntry[] = [];
|
||||
|
||||
if (isUncheckedFile(sourceFile, compilerOptions)) {
|
||||
const uniqueNames = getCompletionEntriesFromSymbols(symbols, entries, location, sourceFile, typeChecker, compilerOptions.target, log, completionKind, preferences, propertyAccessToConvert, isJsxInitializer, recommendedCompletion, symbolToOriginInfoMap);
|
||||
getJavaScriptCompletionEntries(sourceFile, location.pos, uniqueNames, compilerOptions.target, entries);
|
||||
const uniqueNames = getCompletionEntriesFromSymbols(symbols, entries, location, sourceFile, typeChecker, compilerOptions.target!, log, completionKind, preferences, propertyAccessToConvert, isJsxInitializer, recommendedCompletion, symbolToOriginInfoMap);
|
||||
getJavaScriptCompletionEntries(sourceFile, location!.pos, uniqueNames, compilerOptions.target!, entries); // TODO: GH#18217
|
||||
}
|
||||
else {
|
||||
if ((!symbols || symbols.length === 0) && keywordFilters === KeywordCompletionFilters.None) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
getCompletionEntriesFromSymbols(symbols, entries, location, sourceFile, typeChecker, compilerOptions.target, log, completionKind, preferences, propertyAccessToConvert, isJsxInitializer, recommendedCompletion, symbolToOriginInfoMap);
|
||||
getCompletionEntriesFromSymbols(symbols, entries, location, sourceFile, typeChecker, compilerOptions.target!, log, completionKind, preferences, propertyAccessToConvert, isJsxInitializer, recommendedCompletion, symbolToOriginInfoMap);
|
||||
}
|
||||
|
||||
// TODO add filter for keyword based on type/value/namespace and also location
|
||||
@@ -186,7 +186,7 @@ namespace ts.Completions {
|
||||
|
||||
function createCompletionEntry(
|
||||
symbol: Symbol,
|
||||
location: Node,
|
||||
location: Node | undefined,
|
||||
sourceFile: SourceFile,
|
||||
typeChecker: TypeChecker,
|
||||
target: ScriptTarget,
|
||||
@@ -194,7 +194,7 @@ namespace ts.Completions {
|
||||
origin: SymbolOriginInfo | undefined,
|
||||
recommendedCompletion: Symbol | undefined,
|
||||
propertyAccessToConvert: PropertyAccessExpression | undefined,
|
||||
isJsxInitializer: IsJsxInitializer,
|
||||
isJsxInitializer: IsJsxInitializer | undefined,
|
||||
preferences: UserPreferences,
|
||||
): CompletionEntry | undefined {
|
||||
const info = getCompletionEntryDisplayNameForSymbol(symbol, target, origin, kind);
|
||||
@@ -212,7 +212,7 @@ namespace ts.Completions {
|
||||
// Somehow there was a global with a non-identifier name. Hopefully someone will complain about getting a "foo bar" global completion and provide a repro.
|
||||
else if ((origin && origin.type === "symbol-member" || needsConvertPropertyAccess) && propertyAccessToConvert) {
|
||||
insertText = needsConvertPropertyAccess ? `[${quote(name, preferences)}]` : `[${name}]`;
|
||||
const dot = findChildOfKind(propertyAccessToConvert!, SyntaxKind.DotToken, sourceFile)!;
|
||||
const dot = findChildOfKind(propertyAccessToConvert, SyntaxKind.DotToken, sourceFile)!;
|
||||
// If the text after the '.' starts with this name, write over it. Else, add new text.
|
||||
const end = startsWith(name, propertyAccessToConvert.name.text) ? propertyAccessToConvert.name.end : dot.end;
|
||||
replacementSpan = createTextSpanFromBounds(dot.getStart(sourceFile), end);
|
||||
@@ -240,7 +240,7 @@ namespace ts.Completions {
|
||||
// entries (like JavaScript identifier entries).
|
||||
return {
|
||||
name,
|
||||
kind: SymbolDisplay.getSymbolKind(typeChecker, symbol, location),
|
||||
kind: SymbolDisplay.getSymbolKind(typeChecker, symbol, location!), // TODO: GH#18217
|
||||
kindModifiers: SymbolDisplay.getSymbolModifiers(symbol),
|
||||
sortText: "0",
|
||||
source: getSourceFromOrigin(origin),
|
||||
@@ -264,7 +264,7 @@ namespace ts.Completions {
|
||||
}
|
||||
}
|
||||
|
||||
function isRecommendedCompletionMatch(localSymbol: Symbol, recommendedCompletion: Symbol, checker: TypeChecker): boolean {
|
||||
function isRecommendedCompletionMatch(localSymbol: Symbol, recommendedCompletion: Symbol | undefined, checker: TypeChecker): boolean {
|
||||
return localSymbol === recommendedCompletion ||
|
||||
!!(localSymbol.flags & SymbolFlags.ExportValue) && checker.getExportSymbolOfSymbol(localSymbol) === recommendedCompletion;
|
||||
}
|
||||
@@ -280,7 +280,7 @@ namespace ts.Completions {
|
||||
function getCompletionEntriesFromSymbols(
|
||||
symbols: ReadonlyArray<Symbol>,
|
||||
entries: Push<CompletionEntry>,
|
||||
location: Node,
|
||||
location: Node | undefined,
|
||||
sourceFile: SourceFile,
|
||||
typeChecker: TypeChecker,
|
||||
target: ScriptTarget,
|
||||
@@ -311,7 +311,7 @@ namespace ts.Completions {
|
||||
}
|
||||
|
||||
// Latter case tests whether this is a global variable.
|
||||
if (!origin && !(symbol.parent === undefined && !some(symbol.declarations, d => d.getSourceFile() === location.getSourceFile()))) {
|
||||
if (!origin && !(symbol.parent === undefined && !some(symbol.declarations, d => d.getSourceFile() === location!.getSourceFile()))) { // TODO: GH#18217
|
||||
uniques.set(name, true);
|
||||
}
|
||||
|
||||
@@ -460,7 +460,7 @@ namespace ts.Completions {
|
||||
checker.getResolvedSignature(argumentInfo.invocation, candidates, argumentInfo.argumentCount);
|
||||
const types = flatMap(candidates, candidate => {
|
||||
if (!candidate.hasRestParameter && argumentInfo.argumentCount > candidate.parameters.length) return;
|
||||
const type = checker.getParameterType(candidate, argumentInfo.argumentIndex);
|
||||
const type = checker.getParameterType(candidate, argumentInfo.argumentIndex!); // TODO: GH#18217
|
||||
isNewIdentifier = isNewIdentifier || !!(type.flags & TypeFlags.String);
|
||||
return getStringLiteralTypes(type, checker, uniques);
|
||||
});
|
||||
@@ -472,7 +472,7 @@ namespace ts.Completions {
|
||||
return type && { kind: StringLiteralCompletionKind.Properties, symbols: type.getApparentProperties(), hasIndexSignature: hasIndexSignature(type) };
|
||||
}
|
||||
|
||||
function getStringLiteralTypes(type: Type | undefined, typeChecker: TypeChecker, uniques = createMap<true>()): ReadonlyArray<StringLiteralType> | undefined {
|
||||
function getStringLiteralTypes(type: Type | undefined, typeChecker: TypeChecker, uniques = createMap<true>()): ReadonlyArray<StringLiteralType> {
|
||||
if (!type) return emptyArray;
|
||||
type = skipConstraint(type);
|
||||
return type.isUnion()
|
||||
@@ -485,9 +485,9 @@ namespace ts.Completions {
|
||||
interface SymbolCompletion {
|
||||
type: "symbol";
|
||||
symbol: Symbol;
|
||||
location: Node;
|
||||
location: Node | undefined;
|
||||
symbolToOriginInfoMap: SymbolOriginInfoMap;
|
||||
previousToken: Node;
|
||||
previousToken: Node | undefined;
|
||||
readonly isJsxInitializer: IsJsxInitializer;
|
||||
}
|
||||
function getSymbolCompletionFromEntryId(program: Program, log: Log, sourceFile: SourceFile, position: number, entryId: CompletionEntryIdentifier,
|
||||
@@ -507,9 +507,9 @@ namespace ts.Completions {
|
||||
// We don't need to perform character checks here because we're only comparing the
|
||||
// name against 'entryName' (which is known to be good), not building a new
|
||||
// completion entry.
|
||||
return firstDefined<Symbol, SymbolCompletion>(symbols, (symbol): SymbolCompletion => { // TODO: Shouldn't need return type annotation (GH#12632)
|
||||
return firstDefined<Symbol, SymbolCompletion>(symbols, (symbol): SymbolCompletion | undefined => { // TODO: Shouldn't need return type annotation (GH#12632)
|
||||
const origin = symbolToOriginInfoMap[getSymbolId(symbol)];
|
||||
const info = getCompletionEntryDisplayNameForSymbol(symbol, compilerOptions.target, origin, completionKind);
|
||||
const info = getCompletionEntryDisplayNameForSymbol(symbol, compilerOptions.target!, origin, completionKind);
|
||||
return info && info.name === entryId.name && getSourceFromOrigin(origin) === entryId.source
|
||||
? { type: "symbol" as "symbol", symbol, location, symbolToOriginInfoMap, previousToken, isJsxInitializer }
|
||||
: undefined;
|
||||
@@ -540,7 +540,7 @@ namespace ts.Completions {
|
||||
getCanonicalFileName: GetCanonicalFileName,
|
||||
preferences: UserPreferences,
|
||||
cancellationToken: CancellationToken,
|
||||
): CompletionEntryDetails {
|
||||
): CompletionEntryDetails | undefined {
|
||||
const typeChecker = program.getTypeChecker();
|
||||
const compilerOptions = program.getCompilerOptions();
|
||||
const { name } = entryId;
|
||||
@@ -550,7 +550,7 @@ namespace ts.Completions {
|
||||
const stringLiteralCompletions = !contextToken || !isStringLiteralLike(contextToken)
|
||||
? undefined
|
||||
: getStringLiteralCompletionEntries(sourceFile, contextToken, position, typeChecker, compilerOptions, host);
|
||||
return stringLiteralCompletions && stringLiteralCompletionDetails(name, contextToken, stringLiteralCompletions, sourceFile, typeChecker, cancellationToken);
|
||||
return stringLiteralCompletions && stringLiteralCompletionDetails(name, contextToken!, stringLiteralCompletions, sourceFile, typeChecker, cancellationToken); // TODO: GH#18217
|
||||
}
|
||||
|
||||
// Compute all the completion symbols again.
|
||||
@@ -572,7 +572,7 @@ namespace ts.Completions {
|
||||
case "symbol": {
|
||||
const { symbol, location, symbolToOriginInfoMap, previousToken } = symbolCompletion;
|
||||
const { codeActions, sourceDisplay } = getCompletionEntryCodeActionsAndSourceDisplay(symbolToOriginInfoMap, symbol, program, typeChecker, host, compilerOptions, sourceFile, previousToken, formatContext, getCanonicalFileName, program.getSourceFiles(), preferences);
|
||||
return createCompletionDetailsForSymbol(symbol, typeChecker, sourceFile, location, cancellationToken, codeActions, sourceDisplay);
|
||||
return createCompletionDetailsForSymbol(symbol, typeChecker, sourceFile, location!, cancellationToken, codeActions, sourceDisplay); // TODO: GH#18217
|
||||
}
|
||||
case "none":
|
||||
// Didn't find a symbol with this name. See if we can find a keyword instead.
|
||||
@@ -621,7 +621,7 @@ namespace ts.Completions {
|
||||
host: LanguageServiceHost,
|
||||
compilerOptions: CompilerOptions,
|
||||
sourceFile: SourceFile,
|
||||
previousToken: Node,
|
||||
previousToken: Node | undefined,
|
||||
formatContext: formatting.FormatContext,
|
||||
getCanonicalFileName: GetCanonicalFileName,
|
||||
allSourceFiles: ReadonlyArray<SourceFile>,
|
||||
@@ -638,7 +638,7 @@ namespace ts.Completions {
|
||||
exportedSymbol,
|
||||
moduleSymbol,
|
||||
sourceFile,
|
||||
getSymbolName(symbol, symbolOriginInfo, compilerOptions.target),
|
||||
getSymbolName(symbol, symbolOriginInfo, compilerOptions.target!),
|
||||
host,
|
||||
program,
|
||||
checker,
|
||||
@@ -705,7 +705,7 @@ namespace ts.Completions {
|
||||
case SyntaxKind.EqualsToken:
|
||||
switch (parent.kind) {
|
||||
case SyntaxKind.VariableDeclaration:
|
||||
return checker.getContextualType((parent as VariableDeclaration).initializer);
|
||||
return checker.getContextualType((parent as VariableDeclaration).initializer!); // TODO: GH#18217
|
||||
case SyntaxKind.BinaryExpression:
|
||||
return checker.getTypeAtLocation((parent as BinaryExpression).left);
|
||||
case SyntaxKind.JsxAttribute:
|
||||
@@ -723,7 +723,7 @@ namespace ts.Completions {
|
||||
const argInfo = SignatureHelp.getImmediatelyContainingArgumentInfo(currentToken, position, sourceFile);
|
||||
return argInfo
|
||||
// At `,`, treat this as the next argument after the comma.
|
||||
? checker.getContextualTypeForArgumentAtIndex(argInfo.invocation, argInfo.argumentIndex + (currentToken.kind === SyntaxKind.CommaToken ? 1 : 0))
|
||||
? checker.getContextualTypeForArgumentAtIndex(argInfo.invocation, argInfo.argumentIndex! + (currentToken.kind === SyntaxKind.CommaToken ? 1 : 0)) // TODO: GH#18217
|
||||
: isEqualityOperatorKind(currentToken.kind) && isBinaryExpression(parent) && isEqualityOperatorKind(parent.operatorToken.kind)
|
||||
// completion at `x ===/**/` should be for the right side
|
||||
? checker.getTypeAtLocation(parent.left)
|
||||
@@ -749,7 +749,7 @@ namespace ts.Completions {
|
||||
}
|
||||
}
|
||||
|
||||
function getSwitchedType(caseClause: CaseClause, checker: TypeChecker): Type {
|
||||
function getSwitchedType(caseClause: CaseClause, checker: TypeChecker): Type | undefined {
|
||||
return checker.getTypeAtLocation(caseClause.parent.parent.expression);
|
||||
}
|
||||
|
||||
@@ -850,7 +850,7 @@ namespace ts.Completions {
|
||||
}
|
||||
|
||||
start = timestamp();
|
||||
const previousToken = findPrecedingToken(position, sourceFile, /*startNode*/ undefined, insideJsDocTagTypeExpression);
|
||||
const previousToken = findPrecedingToken(position, sourceFile, /*startNode*/ undefined, insideJsDocTagTypeExpression)!; // TODO: GH#18217
|
||||
log("getCompletionData: Get previous token 1: " + (timestamp() - start));
|
||||
|
||||
// The decision to provide completion depends on the contextToken, which is determined through the previousToken.
|
||||
@@ -861,7 +861,7 @@ namespace ts.Completions {
|
||||
// Skip this partial identifier and adjust the contextToken to the token that precedes it.
|
||||
if (contextToken && position <= contextToken.end && (isIdentifier(contextToken) || isKeyword(contextToken.kind))) {
|
||||
const start = timestamp();
|
||||
contextToken = findPrecedingToken(contextToken.getFullStart(), sourceFile, /*startNode*/ undefined, insideJsDocTagTypeExpression);
|
||||
contextToken = findPrecedingToken(contextToken.getFullStart(), sourceFile, /*startNode*/ undefined, insideJsDocTagTypeExpression)!; // TODO: GH#18217
|
||||
log("getCompletionData: Get previous token 2: " + (timestamp() - start));
|
||||
}
|
||||
|
||||
@@ -1017,6 +1017,8 @@ namespace ts.Completions {
|
||||
case SyntaxKind.JSDocTypeTag:
|
||||
case SyntaxKind.JSDocTypedefTag:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1060,7 +1062,7 @@ namespace ts.Completions {
|
||||
}
|
||||
|
||||
if (!isTypeLocation) {
|
||||
addTypeProperties(typeChecker.getTypeAtLocation(node));
|
||||
addTypeProperties(typeChecker.getTypeAtLocation(node)!);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1131,7 +1133,7 @@ namespace ts.Completions {
|
||||
// Cursor is inside a JSX self-closing element or opening element
|
||||
const attrsType = jsxContainer && typeChecker.getAllAttributesTypeFromJsxOpeningLikeElement(jsxContainer);
|
||||
if (!attrsType) return GlobalsSearch.Continue;
|
||||
symbols = filterJsxAttributes(typeChecker.getPropertiesOfType(attrsType), jsxContainer.attributes.properties);
|
||||
symbols = filterJsxAttributes(typeChecker.getPropertiesOfType(attrsType), jsxContainer!.attributes.properties);
|
||||
completionKind = CompletionKind.MemberLike;
|
||||
isNewIdentifierLocation = false;
|
||||
return GlobalsSearch.Success;
|
||||
@@ -1197,7 +1199,7 @@ namespace ts.Completions {
|
||||
}
|
||||
|
||||
if (shouldOfferImportCompletions()) {
|
||||
getSymbolsFromOtherSourceFileExports(symbols, previousToken && isIdentifier(previousToken) ? previousToken.text : "", program.getCompilerOptions().target);
|
||||
getSymbolsFromOtherSourceFileExports(symbols, previousToken && isIdentifier(previousToken) ? previousToken.text : "", program.getCompilerOptions().target!);
|
||||
}
|
||||
filterGlobalCompletion(symbols);
|
||||
}
|
||||
@@ -1305,6 +1307,7 @@ namespace ts.Completions {
|
||||
// symbol can be referenced at locations where type is allowed
|
||||
return exportedSymbols.some(symbolCanBeReferencedAtTypeLocation);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function getSymbolsFromOtherSourceFileExports(symbols: Symbol[], tokenText: string, target: ScriptTarget): void {
|
||||
@@ -1323,7 +1326,7 @@ namespace ts.Completions {
|
||||
//
|
||||
// If `symbol.parent !== ...`, this comes from an `export * from "foo"` re-export. Those don't create new symbols.
|
||||
// If `some(...)`, this comes from an `export { foo } from "foo"` re-export, which creates a new symbol (thus isn't caught by the first check).
|
||||
if (typeChecker.getMergedSymbol(symbol.parent) !== typeChecker.resolveExternalModuleSymbol(moduleSymbol)
|
||||
if (typeChecker.getMergedSymbol(symbol.parent!) !== typeChecker.resolveExternalModuleSymbol(moduleSymbol)
|
||||
|| some(symbol.declarations, d => isExportSpecifier(d) && !!d.parent.parent.moduleSpecifier)) {
|
||||
continue;
|
||||
}
|
||||
@@ -1370,8 +1373,8 @@ namespace ts.Completions {
|
||||
* Finds the first node that "embraces" the position, so that one may
|
||||
* accurately aggregate locals from the closest containing scope.
|
||||
*/
|
||||
function getScopeNode(initialToken: Node, position: number, sourceFile: SourceFile) {
|
||||
let scope = initialToken;
|
||||
function getScopeNode(initialToken: Node | undefined, position: number, sourceFile: SourceFile) {
|
||||
let scope: Node | undefined = initialToken;
|
||||
while (scope && !positionBelongsToNode(scope, position, sourceFile)) {
|
||||
scope = scope.parent;
|
||||
}
|
||||
@@ -1399,13 +1402,13 @@ namespace ts.Completions {
|
||||
}
|
||||
|
||||
if (contextToken.parent.kind === SyntaxKind.JsxClosingElement || contextToken.parent.kind === SyntaxKind.JsxSelfClosingElement) {
|
||||
return contextToken.parent.parent && contextToken.parent.parent.kind === SyntaxKind.JsxElement;
|
||||
return !!contextToken.parent.parent && contextToken.parent.parent.kind === SyntaxKind.JsxElement;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function isNewIdentifierDefinitionLocation(previousToken: Node): boolean {
|
||||
function isNewIdentifierDefinitionLocation(previousToken: Node | undefined): boolean {
|
||||
if (previousToken) {
|
||||
const containingNodeKind = previousToken.parent.kind;
|
||||
switch (previousToken.kind) {
|
||||
@@ -1504,8 +1507,8 @@ namespace ts.Completions {
|
||||
// We're looking up possible property names from contextual/inferred/declared type.
|
||||
completionKind = CompletionKind.ObjectPropertyDeclaration;
|
||||
|
||||
let typeMembers: Symbol[];
|
||||
let existingMembers: ReadonlyArray<Declaration>;
|
||||
let typeMembers: Symbol[] | undefined;
|
||||
let existingMembers: ReadonlyArray<Declaration> | undefined;
|
||||
|
||||
if (objectLikeContainer.kind === SyntaxKind.ObjectLiteralExpression) {
|
||||
const typeForObject = typeChecker.getContextualType(objectLikeContainer);
|
||||
@@ -1576,7 +1579,7 @@ namespace ts.Completions {
|
||||
// cursor is in an import clause
|
||||
// try to show exported member for imported module
|
||||
const { moduleSpecifier } = namedImportsOrExports.kind === SyntaxKind.NamedImports ? namedImportsOrExports.parent.parent : namedImportsOrExports.parent;
|
||||
const moduleSpecifierSymbol = typeChecker.getSymbolAtLocation(moduleSpecifier);
|
||||
const moduleSpecifierSymbol = typeChecker.getSymbolAtLocation(moduleSpecifier!); // TODO: GH#18217
|
||||
if (!moduleSpecifierSymbol) return GlobalsSearch.Fail;
|
||||
|
||||
completionKind = CompletionKind.MemberLike;
|
||||
@@ -1605,7 +1608,7 @@ namespace ts.Completions {
|
||||
if (!isClassLike(decl)) return GlobalsSearch.Success;
|
||||
|
||||
const classElement = contextToken.parent;
|
||||
let classElementModifierFlags = isClassElement(classElement) && getModifierFlags(classElement);
|
||||
let classElementModifierFlags = isClassElement(classElement) ? getModifierFlags(classElement) : ModifierFlags.None;
|
||||
// If this is context token is not something we are editing now, consider if this would lead to be modifier
|
||||
if (contextToken.kind === SyntaxKind.Identifier && !isCurrentlyEditingNode(contextToken)) {
|
||||
switch (contextToken.getText()) {
|
||||
@@ -1622,7 +1625,7 @@ namespace ts.Completions {
|
||||
if (!(classElementModifierFlags & ModifierFlags.Private)) {
|
||||
// List of property symbols of base type that are not private and already implemented
|
||||
const baseSymbols = flatMap(getAllSuperTypeNodes(decl), baseTypeNode => {
|
||||
const type = typeChecker.getTypeAtLocation(baseTypeNode);
|
||||
const type = typeChecker.getTypeAtLocation(baseTypeNode)!; // TODO: GH#18217
|
||||
return typeChecker.getPropertiesOfType(classElementModifierFlags & ModifierFlags.Static ? typeChecker.getTypeOfSymbolAtLocation(type.symbol, decl) : type);
|
||||
});
|
||||
symbols = filterClassMembersList(baseSymbols, decl.members, classElementModifierFlags);
|
||||
@@ -1635,7 +1638,7 @@ namespace ts.Completions {
|
||||
* Returns the immediate owning object literal or binding pattern of a context token,
|
||||
* on the condition that one exists and that the context implies completion should be given.
|
||||
*/
|
||||
function tryGetObjectLikeCompletionContainer(contextToken: Node): ObjectLiteralExpression | ObjectBindingPattern {
|
||||
function tryGetObjectLikeCompletionContainer(contextToken: Node): ObjectLiteralExpression | ObjectBindingPattern | undefined {
|
||||
if (contextToken) {
|
||||
switch (contextToken.kind) {
|
||||
case SyntaxKind.OpenBraceToken: // const x = { |
|
||||
@@ -1660,23 +1663,24 @@ namespace ts.Completions {
|
||||
* Returns the immediate owning class declaration of a context token,
|
||||
* on the condition that one exists and that the context implies completion should be given.
|
||||
*/
|
||||
function tryGetConstructorLikeCompletionContainer(contextToken: Node): ConstructorDeclaration {
|
||||
function tryGetConstructorLikeCompletionContainer(contextToken: Node): ConstructorDeclaration | undefined {
|
||||
if (contextToken) {
|
||||
const parent = contextToken.parent;
|
||||
switch (contextToken.kind) {
|
||||
case SyntaxKind.OpenParenToken:
|
||||
case SyntaxKind.CommaToken:
|
||||
return isConstructorDeclaration(contextToken.parent) && contextToken.parent;
|
||||
return isConstructorDeclaration(contextToken.parent) ? contextToken.parent : undefined;
|
||||
|
||||
default:
|
||||
if (isConstructorParameterCompletion(contextToken)) {
|
||||
return contextToken.parent.parent as ConstructorDeclaration;
|
||||
return parent.parent as ConstructorDeclaration;
|
||||
}
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function tryGetFunctionLikeBodyCompletionContainer(contextToken: Node): FunctionLikeDeclaration {
|
||||
function tryGetFunctionLikeBodyCompletionContainer(contextToken: Node): FunctionLikeDeclaration | undefined {
|
||||
if (contextToken) {
|
||||
let prev: Node;
|
||||
const container = findAncestor(contextToken.parent, (node: Node) => {
|
||||
@@ -1687,12 +1691,13 @@ namespace ts.Completions {
|
||||
return true;
|
||||
}
|
||||
prev = node;
|
||||
return false;
|
||||
});
|
||||
return container && container as FunctionLikeDeclaration;
|
||||
}
|
||||
}
|
||||
|
||||
function tryGetContainingJsxElement(contextToken: Node): JsxOpeningLikeElement {
|
||||
function tryGetContainingJsxElement(contextToken: Node): JsxOpeningLikeElement | undefined {
|
||||
if (contextToken) {
|
||||
const parent = contextToken.parent;
|
||||
switch (contextToken.kind) {
|
||||
@@ -1759,7 +1764,8 @@ namespace ts.Completions {
|
||||
* @returns true if we are certain that the currently edited location must define a new location; false otherwise.
|
||||
*/
|
||||
function isSolelyIdentifierDefinitionLocation(contextToken: Node): boolean {
|
||||
const containingNodeKind = contextToken.parent.kind;
|
||||
const parent = contextToken.parent;
|
||||
const containingNodeKind = parent.kind;
|
||||
switch (contextToken.kind) {
|
||||
case SyntaxKind.CommaToken:
|
||||
return containingNodeKind === SyntaxKind.VariableDeclaration ||
|
||||
@@ -1772,9 +1778,9 @@ namespace ts.Completions {
|
||||
containingNodeKind === SyntaxKind.TypeAliasDeclaration || // type Map, K, |
|
||||
// class A<T, |
|
||||
// var C = class D<T, |
|
||||
(isClassLike(contextToken.parent) &&
|
||||
contextToken.parent.typeParameters &&
|
||||
contextToken.parent.typeParameters.end >= contextToken.pos);
|
||||
(isClassLike(parent) &&
|
||||
!!parent.typeParameters &&
|
||||
parent.typeParameters.end >= contextToken.pos);
|
||||
|
||||
case SyntaxKind.DotToken:
|
||||
return containingNodeKind === SyntaxKind.ArrayBindingPattern; // var [.|
|
||||
@@ -1800,17 +1806,16 @@ namespace ts.Completions {
|
||||
isFunctionLikeKind(containingNodeKind);
|
||||
|
||||
case SyntaxKind.StaticKeyword:
|
||||
return containingNodeKind === SyntaxKind.PropertyDeclaration && !isClassLike(contextToken.parent.parent);
|
||||
return containingNodeKind === SyntaxKind.PropertyDeclaration && !isClassLike(parent.parent);
|
||||
|
||||
case SyntaxKind.DotDotDotToken:
|
||||
return containingNodeKind === SyntaxKind.Parameter ||
|
||||
(contextToken.parent && contextToken.parent.parent &&
|
||||
contextToken.parent.parent.kind === SyntaxKind.ArrayBindingPattern); // var [...z|
|
||||
(!!parent.parent && parent.parent.kind === SyntaxKind.ArrayBindingPattern); // var [...z|
|
||||
|
||||
case SyntaxKind.PublicKeyword:
|
||||
case SyntaxKind.PrivateKeyword:
|
||||
case SyntaxKind.ProtectedKeyword:
|
||||
return containingNodeKind === SyntaxKind.Parameter && !isConstructorDeclaration(contextToken.parent.parent);
|
||||
return containingNodeKind === SyntaxKind.Parameter && !isConstructorDeclaration(parent.parent);
|
||||
|
||||
case SyntaxKind.AsKeyword:
|
||||
return containingNodeKind === SyntaxKind.ImportSpecifier ||
|
||||
@@ -1922,12 +1927,12 @@ namespace ts.Completions {
|
||||
continue;
|
||||
}
|
||||
|
||||
let existingName: __String;
|
||||
let existingName: __String | undefined;
|
||||
|
||||
if (m.kind === SyntaxKind.BindingElement && (<BindingElement>m).propertyName) {
|
||||
if (isBindingElement(m) && m.propertyName) {
|
||||
// include only identifiers in completion list
|
||||
if ((<BindingElement>m).propertyName.kind === SyntaxKind.Identifier) {
|
||||
existingName = (<Identifier>(<BindingElement>m).propertyName).escapedText;
|
||||
if (m.propertyName.kind === SyntaxKind.Identifier) {
|
||||
existingName = m.propertyName.escapedText;
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -1938,7 +1943,7 @@ namespace ts.Completions {
|
||||
existingName = isPropertyNameLiteral(name) ? getEscapedTextOfIdentifierOrLiteral(name) : undefined;
|
||||
}
|
||||
|
||||
existingMemberNames.set(existingName, true);
|
||||
existingMemberNames.set(existingName!, true); // TODO: GH#18217
|
||||
}
|
||||
|
||||
return contextualMemberSymbols.filter(m => !existingMemberNames.get(m.escapedName));
|
||||
@@ -1975,7 +1980,7 @@ namespace ts.Completions {
|
||||
continue;
|
||||
}
|
||||
|
||||
const existingName = getPropertyNameForPropertyNameNode(m.name);
|
||||
const existingName = getPropertyNameForPropertyNameNode(m.name!);
|
||||
if (existingName) {
|
||||
existingMemberNames.set(existingName, true);
|
||||
}
|
||||
@@ -2060,7 +2065,7 @@ namespace ts.Completions {
|
||||
const res: CompletionEntry[] = [];
|
||||
for (let i = SyntaxKind.FirstKeyword; i <= SyntaxKind.LastKeyword; i++) {
|
||||
res.push({
|
||||
name: tokenToString(i),
|
||||
name: tokenToString(i)!,
|
||||
kind: ScriptElementKind.keyword,
|
||||
kindModifiers: ScriptElementKindModifier.none,
|
||||
sortText: "0"
|
||||
@@ -2070,7 +2075,7 @@ namespace ts.Completions {
|
||||
});
|
||||
function getKeywordCompletions(keywordFilter: KeywordCompletionFilters): ReadonlyArray<CompletionEntry> {
|
||||
return _keywordCompletions[keywordFilter] || (_keywordCompletions[keywordFilter] = allKeywordsCompletions().filter(entry => {
|
||||
const kind = stringToToken(entry.name);
|
||||
const kind = stringToToken(entry.name)!;
|
||||
switch (keywordFilter) {
|
||||
case KeywordCompletionFilters.None:
|
||||
// "undefined" is a global variable, so don't need a keyword completion for it.
|
||||
@@ -2199,7 +2204,7 @@ namespace ts.Completions {
|
||||
default:
|
||||
if (!isFromObjectTypeDeclaration(contextToken)) return undefined;
|
||||
const isValidKeyword = isClassLike(contextToken.parent.parent) ? isClassMemberCompletionKeyword : isInterfaceOrTypeLiteralCompletionKeyword;
|
||||
return (isValidKeyword(contextToken.kind) || isIdentifier(contextToken) && isValidKeyword(stringToToken(contextToken.text)))
|
||||
return (isValidKeyword(contextToken.kind) || isIdentifier(contextToken) && isValidKeyword(stringToToken(contextToken.text)!)) // TODO: GH#18217
|
||||
? contextToken.parent.parent as ObjectTypeDeclaration : undefined;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,7 +30,7 @@ namespace ts.DocumentHighlights {
|
||||
if (!sourceFilesSet.has(fileName)) {
|
||||
Debug.assert(program.redirectTargetsSet.has(fileName));
|
||||
const redirectTarget = program.getSourceFile(fileName);
|
||||
const redirect = find(sourceFilesToSearch, f => f.redirectInfo && f.redirectInfo.redirectTarget === redirectTarget)!;
|
||||
const redirect = find(sourceFilesToSearch, f => !!f.redirectInfo && f.redirectInfo.redirectTarget === redirectTarget)!;
|
||||
fileName = redirect.fileName;
|
||||
Debug.assert(sourceFilesSet.has(fileName));
|
||||
}
|
||||
@@ -38,7 +38,7 @@ namespace ts.DocumentHighlights {
|
||||
});
|
||||
}
|
||||
|
||||
function getSyntacticDocumentHighlights(node: Node, sourceFile: SourceFile): DocumentHighlights[] {
|
||||
function getSyntacticDocumentHighlights(node: Node, sourceFile: SourceFile): DocumentHighlights[] | undefined {
|
||||
const highlightSpans = getHighlightSpans(node, sourceFile);
|
||||
return highlightSpans && [{ fileName: sourceFile.fileName, highlightSpans }];
|
||||
}
|
||||
@@ -110,7 +110,7 @@ namespace ts.DocumentHighlights {
|
||||
// Exceptions thrown within a try block lacking a catch clause are "owned" in the current context.
|
||||
return concatenate(
|
||||
node.catchClause ? aggregateOwnedThrowStatements(node.catchClause) : node.tryBlock && aggregateOwnedThrowStatements(node.tryBlock),
|
||||
aggregateOwnedThrowStatements(node.finallyBlock));
|
||||
node.finallyBlock && aggregateOwnedThrowStatements(node.finallyBlock));
|
||||
}
|
||||
// Do not cross function boundaries.
|
||||
return isFunctionLike(node) ? undefined : flatMapChildren(node, aggregateOwnedThrowStatements);
|
||||
@@ -121,7 +121,7 @@ namespace ts.DocumentHighlights {
|
||||
* nearest ancestor that is a try-block (whose try statement has a catch clause),
|
||||
* function-block, or source file.
|
||||
*/
|
||||
function getThrowStatementOwner(throwStatement: ThrowStatement): Node {
|
||||
function getThrowStatementOwner(throwStatement: ThrowStatement): Node | undefined {
|
||||
let child: Node = throwStatement;
|
||||
|
||||
while (child.parent) {
|
||||
@@ -160,11 +160,10 @@ namespace ts.DocumentHighlights {
|
||||
|
||||
function ownsBreakOrContinueStatement(owner: Node, statement: BreakOrContinueStatement): boolean {
|
||||
const actualOwner = getBreakOrContinueOwner(statement);
|
||||
|
||||
return actualOwner && actualOwner === owner;
|
||||
return !!actualOwner && actualOwner === owner;
|
||||
}
|
||||
|
||||
function getBreakOrContinueOwner(statement: BreakOrContinueStatement): Node {
|
||||
function getBreakOrContinueOwner(statement: BreakOrContinueStatement): Node | undefined {
|
||||
return findAncestor(statement, node => {
|
||||
switch (node.kind) {
|
||||
case SyntaxKind.SwitchStatement:
|
||||
@@ -190,14 +189,14 @@ namespace ts.DocumentHighlights {
|
||||
const modifierFlag = modifierToFlag(modifier);
|
||||
return mapDefined(getNodesToSearchForModifier(declaration, modifierFlag), node => {
|
||||
if (getModifierFlags(node) & modifierFlag) {
|
||||
const mod = find(node.modifiers, m => m.kind === modifier);
|
||||
const mod = find(node.modifiers!, m => m.kind === modifier);
|
||||
Debug.assert(!!mod);
|
||||
return mod;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function getNodesToSearchForModifier(declaration: Node, modifierFlag: ModifierFlags): ReadonlyArray<Node> {
|
||||
function getNodesToSearchForModifier(declaration: Node, modifierFlag: ModifierFlags): ReadonlyArray<Node> | undefined {
|
||||
// Types of node whose children might have modifiers.
|
||||
const container = declaration.parent as ModuleBlock | SourceFile | Block | CaseClause | DefaultClause | ConstructorDeclaration | MethodDeclaration | FunctionDeclaration | ClassLikeDeclaration;
|
||||
switch (container.kind) {
|
||||
@@ -215,9 +214,8 @@ namespace ts.DocumentHighlights {
|
||||
}
|
||||
case SyntaxKind.Constructor:
|
||||
case SyntaxKind.MethodDeclaration:
|
||||
case SyntaxKind.FunctionDeclaration: {
|
||||
case SyntaxKind.FunctionDeclaration:
|
||||
return [...container.parameters, ...(isClassLike(container.parent) ? container.parent.members : [])];
|
||||
}
|
||||
case SyntaxKind.ClassDeclaration:
|
||||
case SyntaxKind.ClassExpression:
|
||||
const nodes = container.members;
|
||||
@@ -251,7 +249,7 @@ namespace ts.DocumentHighlights {
|
||||
function getLoopBreakContinueOccurrences(loopNode: IterationStatement): Node[] {
|
||||
const keywords: Node[] = [];
|
||||
|
||||
if (pushKeywordIf(keywords, loopNode.getFirstToken(), SyntaxKind.ForKeyword, SyntaxKind.WhileKeyword, SyntaxKind.DoKeyword)) {
|
||||
if (pushKeywordIf(keywords, loopNode.getFirstToken()!, SyntaxKind.ForKeyword, SyntaxKind.WhileKeyword, SyntaxKind.DoKeyword)) {
|
||||
// If we succeeded and got a do-while loop, then start looking for a 'while' keyword.
|
||||
if (loopNode.kind === SyntaxKind.DoStatement) {
|
||||
const loopTokens = loopNode.getChildren();
|
||||
@@ -266,14 +264,14 @@ namespace ts.DocumentHighlights {
|
||||
|
||||
forEach(aggregateAllBreakAndContinueStatements(loopNode.statement), statement => {
|
||||
if (ownsBreakOrContinueStatement(loopNode, statement)) {
|
||||
pushKeywordIf(keywords, statement.getFirstToken(), SyntaxKind.BreakKeyword, SyntaxKind.ContinueKeyword);
|
||||
pushKeywordIf(keywords, statement.getFirstToken()!, SyntaxKind.BreakKeyword, SyntaxKind.ContinueKeyword);
|
||||
}
|
||||
});
|
||||
|
||||
return keywords;
|
||||
}
|
||||
|
||||
function getBreakOrContinueStatementOccurrences(breakOrContinueStatement: BreakOrContinueStatement): Node[] {
|
||||
function getBreakOrContinueStatementOccurrences(breakOrContinueStatement: BreakOrContinueStatement): Node[] | undefined {
|
||||
const owner = getBreakOrContinueOwner(breakOrContinueStatement);
|
||||
|
||||
if (owner) {
|
||||
@@ -296,15 +294,15 @@ namespace ts.DocumentHighlights {
|
||||
function getSwitchCaseDefaultOccurrences(switchStatement: SwitchStatement): Node[] {
|
||||
const keywords: Node[] = [];
|
||||
|
||||
pushKeywordIf(keywords, switchStatement.getFirstToken(), SyntaxKind.SwitchKeyword);
|
||||
pushKeywordIf(keywords, switchStatement.getFirstToken()!, SyntaxKind.SwitchKeyword);
|
||||
|
||||
// Go through each clause in the switch statement, collecting the 'case'/'default' keywords.
|
||||
forEach(switchStatement.caseBlock.clauses, clause => {
|
||||
pushKeywordIf(keywords, clause.getFirstToken(), SyntaxKind.CaseKeyword, SyntaxKind.DefaultKeyword);
|
||||
pushKeywordIf(keywords, clause.getFirstToken()!, SyntaxKind.CaseKeyword, SyntaxKind.DefaultKeyword);
|
||||
|
||||
forEach(aggregateAllBreakAndContinueStatements(clause), statement => {
|
||||
if (ownsBreakOrContinueStatement(switchStatement, statement)) {
|
||||
pushKeywordIf(keywords, statement.getFirstToken(), SyntaxKind.BreakKeyword);
|
||||
pushKeywordIf(keywords, statement.getFirstToken()!, SyntaxKind.BreakKeyword);
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -315,21 +313,21 @@ namespace ts.DocumentHighlights {
|
||||
function getTryCatchFinallyOccurrences(tryStatement: TryStatement, sourceFile: SourceFile): Node[] {
|
||||
const keywords: Node[] = [];
|
||||
|
||||
pushKeywordIf(keywords, tryStatement.getFirstToken(), SyntaxKind.TryKeyword);
|
||||
pushKeywordIf(keywords, tryStatement.getFirstToken()!, SyntaxKind.TryKeyword);
|
||||
|
||||
if (tryStatement.catchClause) {
|
||||
pushKeywordIf(keywords, tryStatement.catchClause.getFirstToken(), SyntaxKind.CatchKeyword);
|
||||
pushKeywordIf(keywords, tryStatement.catchClause.getFirstToken()!, SyntaxKind.CatchKeyword);
|
||||
}
|
||||
|
||||
if (tryStatement.finallyBlock) {
|
||||
const finallyKeyword = findChildOfKind(tryStatement, SyntaxKind.FinallyKeyword, sourceFile);
|
||||
const finallyKeyword = findChildOfKind(tryStatement, SyntaxKind.FinallyKeyword, sourceFile)!;
|
||||
pushKeywordIf(keywords, finallyKeyword, SyntaxKind.FinallyKeyword);
|
||||
}
|
||||
|
||||
return keywords;
|
||||
}
|
||||
|
||||
function getThrowOccurrences(throwStatement: ThrowStatement, sourceFile: SourceFile): Node[] {
|
||||
function getThrowOccurrences(throwStatement: ThrowStatement, sourceFile: SourceFile): Node[] | undefined {
|
||||
const owner = getThrowStatementOwner(throwStatement);
|
||||
|
||||
if (!owner) {
|
||||
@@ -365,7 +363,7 @@ namespace ts.DocumentHighlights {
|
||||
});
|
||||
|
||||
// Include 'throw' statements that do not occur within a try block.
|
||||
forEach(aggregateOwnedThrowStatements(func.body), throwStatement => {
|
||||
forEach(aggregateOwnedThrowStatements(func.body!), throwStatement => {
|
||||
keywords.push(findChildOfKind(throwStatement, SyntaxKind.ThrowKeyword, sourceFile)!);
|
||||
});
|
||||
|
||||
@@ -392,7 +390,7 @@ namespace ts.DocumentHighlights {
|
||||
|
||||
function aggregate(node: Node): void {
|
||||
if (isAwaitExpression(node)) {
|
||||
pushKeywordIf(keywords, node.getFirstToken(), SyntaxKind.AwaitKeyword);
|
||||
pushKeywordIf(keywords, node.getFirstToken()!, SyntaxKind.AwaitKeyword);
|
||||
}
|
||||
// Do not cross function boundaries.
|
||||
if (!isFunctionLike(node) && !isClassLike(node) && !isInterfaceDeclaration(node) && !isModuleDeclaration(node) && !isTypeAliasDeclaration(node) && !isTypeNode(node)) {
|
||||
|
||||
@@ -130,12 +130,12 @@ namespace ts {
|
||||
if (!bucket && createIfMissing) {
|
||||
buckets.set(key, bucket = createMap<DocumentRegistryEntry>());
|
||||
}
|
||||
return bucket;
|
||||
return bucket!; // TODO: GH#18217
|
||||
}
|
||||
|
||||
function reportStats() {
|
||||
const bucketInfoArray = arrayFrom(buckets.keys()).filter(name => name && name.charAt(0) === "_").map(name => {
|
||||
const entries = buckets.get(name);
|
||||
const entries = buckets.get(name)!;
|
||||
const sourceFiles: { name: string; refCount: number; }[] = [];
|
||||
entries.forEach((entry, name) => {
|
||||
sourceFiles.push({
|
||||
@@ -199,7 +199,7 @@ namespace ts {
|
||||
|
||||
if (!entry) {
|
||||
// Have never seen this file with these settings. Create a new source file for it.
|
||||
const sourceFile = createLanguageServiceSourceFile(fileName, scriptSnapshot, scriptTarget, version, /*setNodeParents*/ false, scriptKind);
|
||||
const sourceFile = createLanguageServiceSourceFile(fileName, scriptSnapshot, scriptTarget!, version, /*setNodeParents*/ false, scriptKind); // TODO: GH#18217
|
||||
if (externalCache) {
|
||||
externalCache.setDocument(key, path, sourceFile);
|
||||
}
|
||||
@@ -215,7 +215,7 @@ namespace ts {
|
||||
// return it as is.
|
||||
if (entry.sourceFile.version !== version) {
|
||||
entry.sourceFile = updateLanguageServiceSourceFile(entry.sourceFile, scriptSnapshot, version,
|
||||
scriptSnapshot.getChangeRange(entry.sourceFile.scriptSnapshot));
|
||||
scriptSnapshot.getChangeRange(entry.sourceFile.scriptSnapshot!)); // TODO: GH#18217
|
||||
if (externalCache) {
|
||||
externalCache.setDocument(key, path, entry.sourceFile);
|
||||
}
|
||||
@@ -245,7 +245,7 @@ namespace ts {
|
||||
const bucket = getBucketForCompilationSettings(key, /*createIfMissing*/ false);
|
||||
Debug.assert(bucket !== undefined);
|
||||
|
||||
const entry = bucket.get(path);
|
||||
const entry = bucket.get(path)!;
|
||||
entry.languageServiceRefCount--;
|
||||
|
||||
Debug.assert(entry.languageServiceRefCount >= 0);
|
||||
|
||||
@@ -51,7 +51,7 @@ namespace ts.FindAllReferences {
|
||||
});
|
||||
}
|
||||
|
||||
export function getImplementationsAtPosition(program: Program, cancellationToken: CancellationToken, sourceFiles: ReadonlyArray<SourceFile>, sourceFile: SourceFile, position: number): ImplementationLocation[] {
|
||||
export function getImplementationsAtPosition(program: Program, cancellationToken: CancellationToken, sourceFiles: ReadonlyArray<SourceFile>, sourceFile: SourceFile, position: number): ImplementationLocation[] | undefined {
|
||||
// A node in a JSDoc comment can't have an implementation anyway.
|
||||
const node = getTouchingPropertyName(sourceFile, position, /*includeJsDocComment*/ false);
|
||||
const referenceEntries = getImplementationReferenceEntries(program, cancellationToken, sourceFiles, node, position);
|
||||
@@ -75,7 +75,7 @@ namespace ts.FindAllReferences {
|
||||
else if (node.kind === SyntaxKind.SuperKeyword || isSuperProperty(node.parent)) {
|
||||
// References to and accesses on the super keyword only have one possible implementation, so no
|
||||
// need to "Find all References"
|
||||
const symbol = checker.getSymbolAtLocation(node);
|
||||
const symbol = checker.getSymbolAtLocation(node)!;
|
||||
return symbol.valueDeclaration && [nodeEntry(symbol.valueDeclaration)];
|
||||
}
|
||||
else {
|
||||
@@ -93,11 +93,11 @@ namespace ts.FindAllReferences {
|
||||
return flattenEntries(Core.getReferencedSymbolsForNode(position, node, program, sourceFiles, cancellationToken, options, sourceFilesSet));
|
||||
}
|
||||
|
||||
function flattenEntries(referenceSymbols: SymbolAndEntries[]): Entry[] {
|
||||
function flattenEntries(referenceSymbols: SymbolAndEntries[] | undefined): Entry[] | undefined {
|
||||
return referenceSymbols && flatMap(referenceSymbols, r => r.references);
|
||||
}
|
||||
|
||||
function definitionToReferencedSymbolDefinitionInfo(def: Definition, checker: TypeChecker, originalNode: Node): ReferencedSymbolDefinitionInfo | undefined {
|
||||
function definitionToReferencedSymbolDefinitionInfo(def: Definition, checker: TypeChecker, originalNode: Node): ReferencedSymbolDefinitionInfo {
|
||||
const info = (() => {
|
||||
switch (def.type) {
|
||||
case "symbol": {
|
||||
@@ -112,7 +112,7 @@ namespace ts.FindAllReferences {
|
||||
}
|
||||
case "keyword": {
|
||||
const { node } = def;
|
||||
const name = tokenToString(node.kind);
|
||||
const name = tokenToString(node.kind)!;
|
||||
return { node, name, kind: ScriptElementKind.keyword, displayParts: [{ text: name, kind: ScriptElementKind.keyword }] };
|
||||
}
|
||||
case "this": {
|
||||
@@ -257,20 +257,21 @@ namespace ts.FindAllReferences.Core {
|
||||
|
||||
let moduleReferences: SymbolAndEntries[] = emptyArray;
|
||||
const moduleSourceFile = isModuleSymbol(symbol);
|
||||
let referencedNode: Node | undefined = node;
|
||||
if (moduleSourceFile) {
|
||||
const exportEquals = symbol.exports.get(InternalSymbolName.ExportEquals);
|
||||
const exportEquals = symbol.exports!.get(InternalSymbolName.ExportEquals);
|
||||
// If !!exportEquals, we're about to add references to `import("mod")` anyway, so don't double-count them.
|
||||
moduleReferences = getReferencedSymbolsForModule(program, symbol, !!exportEquals, sourceFiles, sourceFilesSet);
|
||||
if (!exportEquals || !sourceFilesSet.has(moduleSourceFile.fileName)) return moduleReferences;
|
||||
// Continue to get references to 'export ='.
|
||||
symbol = skipAlias(exportEquals, checker);
|
||||
node = undefined;
|
||||
referencedNode = undefined;
|
||||
}
|
||||
return concatenate(moduleReferences, getReferencedSymbolsForSymbol(symbol, node, sourceFiles, sourceFilesSet, checker, cancellationToken, options));
|
||||
return concatenate(moduleReferences, getReferencedSymbolsForSymbol(symbol, referencedNode, sourceFiles, sourceFilesSet, checker, cancellationToken, options));
|
||||
}
|
||||
|
||||
function isModuleSymbol(symbol: Symbol): SourceFile | undefined {
|
||||
return symbol.flags & SymbolFlags.Module && find(symbol.declarations, isSourceFile);
|
||||
return symbol.flags & SymbolFlags.Module ? find(symbol.declarations, isSourceFile) : undefined;
|
||||
}
|
||||
|
||||
function getReferencedSymbolsForModule(program: Program, symbol: Symbol, excludeImportTypeOfExportEquals: boolean, sourceFiles: ReadonlyArray<SourceFile>, sourceFilesSet: ReadonlyMap<true>): SymbolAndEntries[] {
|
||||
@@ -360,7 +361,7 @@ namespace ts.FindAllReferences.Core {
|
||||
searchForImportsOfExport(node, symbol, { exportingModuleSymbol: Debug.assertDefined(symbol.parent, "Expected export symbol to have a parent"), exportKind: ExportKind.Default }, state);
|
||||
}
|
||||
else {
|
||||
const search = state.createSearch(node, symbol, /*comingFrom*/ undefined, { allSearchSymbols: node ? populateSearchSymbolSet(symbol, node, checker, options.implementations) : [symbol] });
|
||||
const search = state.createSearch(node, symbol, /*comingFrom*/ undefined, { allSearchSymbols: node ? populateSearchSymbolSet(symbol, node, checker, !!options.implementations) : [symbol] });
|
||||
|
||||
// Try to get the smallest valid scope that we can limit our search to;
|
||||
// otherwise we'll need to search globally (i.e. include each file).
|
||||
@@ -403,7 +404,7 @@ namespace ts.FindAllReferences.Core {
|
||||
}
|
||||
if (isImportSpecifier(parent) && parent.propertyName === node) {
|
||||
// We're at `foo` in `import { foo as bar }`. Probably intended to find all refs on the original, not just on the import.
|
||||
return checker.getImmediateAliasedSymbol(symbol);
|
||||
return checker.getImmediateAliasedSymbol(symbol)!;
|
||||
}
|
||||
|
||||
// If the symbol is declared as part of a declaration like `{ type: "a" } | { type: "b" }`, use the property on the union type to get more references.
|
||||
@@ -496,7 +497,7 @@ namespace ts.FindAllReferences.Core {
|
||||
/** Gets every place to look for references of an exported symbols. See `ImportsResult` in `importTracker.ts` for more documentation. */
|
||||
getImportSearches(exportSymbol: Symbol, exportInfo: ExportInfo): ImportsResult {
|
||||
if (!this.importTracker) this.importTracker = createImportTracker(this.sourceFiles, this.sourceFilesSet, this.checker, this.cancellationToken);
|
||||
return this.importTracker(exportSymbol, exportInfo, this.options.isForRename);
|
||||
return this.importTracker(exportSymbol, exportInfo, !!this.options.isForRename);
|
||||
}
|
||||
|
||||
/** @param allSearchSymbols set of additinal symbols for use by `includes`. */
|
||||
@@ -510,7 +511,7 @@ namespace ts.FindAllReferences.Core {
|
||||
allSearchSymbols = [symbol],
|
||||
} = searchOptions;
|
||||
const escapedText = escapeLeadingUnderscores(text);
|
||||
const parents = this.options.implementations && location && getParentSymbolsOfPropertyAccess(location, symbol, this.checker);
|
||||
const parents = this.options.implementations && location ? getParentSymbolsOfPropertyAccess(location, symbol, this.checker) : undefined;
|
||||
return { symbol, comingFrom, text, escapedText, parents, allSearchSymbols, includes: sym => contains(allSearchSymbols, sym) };
|
||||
}
|
||||
|
||||
@@ -616,8 +617,9 @@ namespace ts.FindAllReferences.Core {
|
||||
}
|
||||
|
||||
function getPropertySymbolOfDestructuringAssignment(location: Node, checker: TypeChecker): Symbol | undefined {
|
||||
return isArrayLiteralOrObjectLiteralDestructuringPattern(location.parent.parent) &&
|
||||
checker.getPropertySymbolOfDestructuringAssignment(<Identifier>location);
|
||||
return isArrayLiteralOrObjectLiteralDestructuringPattern(location.parent.parent)
|
||||
? checker.getPropertySymbolOfDestructuringAssignment(<Identifier>location)
|
||||
: undefined;
|
||||
}
|
||||
|
||||
function getObjectBindingElementWithoutPropertyName(symbol: Symbol): BindingElement & { name: Identifier } | undefined {
|
||||
@@ -679,7 +681,7 @@ namespace ts.FindAllReferences.Core {
|
||||
- But if the parent has `export as namespace`, the symbol is globally visible through that namespace.
|
||||
*/
|
||||
const exposedByParent = parent && !(symbol.flags & SymbolFlags.TypeParameter);
|
||||
if (exposedByParent && !((parent.flags & SymbolFlags.Module) && isExternalModuleSymbol(parent) && !parent.globalExports)) {
|
||||
if (exposedByParent && !((parent!.flags & SymbolFlags.Module) && isExternalModuleSymbol(parent!) && !parent!.globalExports)) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
@@ -706,7 +708,7 @@ namespace ts.FindAllReferences.Core {
|
||||
// declare module "a" { export type T = number; }
|
||||
// declare module "b" { import { T } from "a"; export const x: T; }
|
||||
// So we must search the whole source file. (Because we will mark the source file as seen, we we won't return to it when searching for imports.)
|
||||
return exposedByParent ? scope.getSourceFile() : scope;
|
||||
return exposedByParent ? scope!.getSourceFile() : scope; // TODO: GH#18217
|
||||
}
|
||||
|
||||
/** Used as a quick check for whether a symbol is used at all in a file (besides its definition). */
|
||||
@@ -715,7 +717,7 @@ namespace ts.FindAllReferences.Core {
|
||||
if (!symbol) return true; // Be lenient with invalid code.
|
||||
return getPossibleSymbolReferenceNodes(sourceFile, symbol.name).some(token => {
|
||||
if (!isIdentifier(token) || token === definition || token.escapedText !== definition.escapedText) return false;
|
||||
const referenceSymbol = checker.getSymbolAtLocation(token);
|
||||
const referenceSymbol = checker.getSymbolAtLocation(token)!;
|
||||
return referenceSymbol === symbol
|
||||
|| checker.getShorthandAssignmentValueSymbol(token.parent) === symbol
|
||||
|| isExportSpecifier(token.parent) && getLocalSymbolForExportSpecifier(token, referenceSymbol, token.parent, checker) === symbol;
|
||||
@@ -793,10 +795,10 @@ namespace ts.FindAllReferences.Core {
|
||||
}
|
||||
}
|
||||
|
||||
function getAllReferencesForKeyword(sourceFiles: ReadonlyArray<SourceFile>, keywordKind: SyntaxKind, cancellationToken: CancellationToken): SymbolAndEntries[] {
|
||||
function getAllReferencesForKeyword(sourceFiles: ReadonlyArray<SourceFile>, keywordKind: SyntaxKind, cancellationToken: CancellationToken): SymbolAndEntries[] | undefined {
|
||||
const references = flatMap(sourceFiles, sourceFile => {
|
||||
cancellationToken.throwIfCancellationRequested();
|
||||
return mapDefined(getPossibleSymbolReferenceNodes(sourceFile, tokenToString(keywordKind), sourceFile), referenceLocation =>
|
||||
return mapDefined(getPossibleSymbolReferenceNodes(sourceFile, tokenToString(keywordKind)!, sourceFile), referenceLocation =>
|
||||
referenceLocation.kind === keywordKind ? nodeEntry(referenceLocation) : undefined);
|
||||
});
|
||||
return references.length ? [{ definition: { type: "keyword", node: references[0].node }, references }] : undefined;
|
||||
@@ -851,7 +853,7 @@ namespace ts.FindAllReferences.Core {
|
||||
return;
|
||||
}
|
||||
|
||||
const { parent } = referenceLocation;
|
||||
const parent = referenceLocation.parent;
|
||||
if (isImportSpecifier(parent) && parent.propertyName === referenceLocation) {
|
||||
// This is added through `singleReferences` in ImportsResult. If we happen to see it again, don't add it again.
|
||||
return;
|
||||
@@ -921,7 +923,7 @@ namespace ts.FindAllReferences.Core {
|
||||
if (!(referenceLocation === propertyName && state.options.isForRename)) {
|
||||
const exportKind = referenceLocation.originalKeywordKind === SyntaxKind.DefaultKeyword ? ExportKind.Default : ExportKind.Named;
|
||||
const exportInfo = getExportInfo(referenceSymbol, exportKind, state.checker);
|
||||
Debug.assert(!!exportInfo);
|
||||
if (!exportInfo) return Debug.fail();
|
||||
searchForImportsOfExport(referenceLocation, referenceSymbol, exportInfo, state);
|
||||
}
|
||||
|
||||
@@ -972,7 +974,7 @@ namespace ts.FindAllReferences.Core {
|
||||
}
|
||||
|
||||
function getReferenceForShorthandProperty({ flags, valueDeclaration }: Symbol, search: Search, state: State): void {
|
||||
const shorthandValueSymbol = state.checker.getShorthandAssignmentValueSymbol(valueDeclaration);
|
||||
const shorthandValueSymbol = state.checker.getShorthandAssignmentValueSymbol(valueDeclaration)!;
|
||||
/*
|
||||
* Because in short-hand property assignment, an identifier which stored as name of the short-hand property assignment
|
||||
* has two meanings: property name and property value. Therefore when we do findAllReference at the position where
|
||||
@@ -1027,7 +1029,7 @@ namespace ts.FindAllReferences.Core {
|
||||
if (!(isMethodOrAccessor(member) && hasModifier(member, ModifierFlags.Static))) {
|
||||
continue;
|
||||
}
|
||||
member.body.forEachChild(function cb(node) {
|
||||
member.body!.forEachChild(function cb(node) {
|
||||
if (node.kind === SyntaxKind.ThisKeyword) {
|
||||
addRef(node);
|
||||
}
|
||||
@@ -1043,13 +1045,13 @@ namespace ts.FindAllReferences.Core {
|
||||
* Reference the constructor and all calls to `new this()`.
|
||||
*/
|
||||
function findOwnConstructorReferences(classSymbol: Symbol, sourceFile: SourceFile, addNode: (node: Node) => void): void {
|
||||
for (const decl of classSymbol.members.get(InternalSymbolName.Constructor).declarations) {
|
||||
for (const decl of classSymbol.members!.get(InternalSymbolName.Constructor)!.declarations) {
|
||||
const ctrKeyword = findChildOfKind(decl, SyntaxKind.ConstructorKeyword, sourceFile)!;
|
||||
Debug.assert(decl.kind === SyntaxKind.Constructor && !!ctrKeyword);
|
||||
addNode(ctrKeyword);
|
||||
}
|
||||
|
||||
classSymbol.exports.forEach(member => {
|
||||
classSymbol.exports!.forEach(member => {
|
||||
const decl = member.valueDeclaration;
|
||||
if (decl && decl.kind === SyntaxKind.MethodDeclaration) {
|
||||
const body = (<MethodDeclaration>decl).body;
|
||||
@@ -1066,8 +1068,7 @@ namespace ts.FindAllReferences.Core {
|
||||
|
||||
/** Find references to `super` in the constructor of an extending class. */
|
||||
function findSuperConstructorAccesses(cls: ClassLikeDeclaration, addNode: (node: Node) => void): void {
|
||||
const symbol = cls.symbol;
|
||||
const ctr = symbol.members.get(InternalSymbolName.Constructor);
|
||||
const ctr = cls.symbol.members!.get(InternalSymbolName.Constructor);
|
||||
if (!ctr) {
|
||||
return;
|
||||
}
|
||||
@@ -1110,14 +1111,14 @@ namespace ts.FindAllReferences.Core {
|
||||
|
||||
// If we got a type reference, try and see if the reference applies to any expressions that can implement an interface
|
||||
// Find the first node whose parent isn't a type node -- i.e., the highest type node.
|
||||
const typeNode = findAncestor(refNode, a => !isQualifiedName(a.parent) && !isTypeNode(a.parent) && !isTypeElement(a.parent));
|
||||
const typeNode = findAncestor(refNode, a => !isQualifiedName(a.parent) && !isTypeNode(a.parent) && !isTypeElement(a.parent))!;
|
||||
const typeHavingNode = typeNode.parent;
|
||||
if (hasType(typeHavingNode) && typeHavingNode.type === typeNode && state.markSeenContainingTypeReference(typeHavingNode)) {
|
||||
if (hasInitializer(typeHavingNode)) {
|
||||
addIfImplementation(typeHavingNode.initializer);
|
||||
addIfImplementation(typeHavingNode.initializer!);
|
||||
}
|
||||
else if (isFunctionLike(typeHavingNode) && (typeHavingNode as FunctionLikeDeclaration).body) {
|
||||
const body = (typeHavingNode as FunctionLikeDeclaration).body;
|
||||
const body = (typeHavingNode as FunctionLikeDeclaration).body!;
|
||||
if (body.kind === SyntaxKind.Block) {
|
||||
forEachReturnStatement(<Block>body, returnStatement => {
|
||||
if (returnStatement.expression) addIfImplementation(returnStatement.expression);
|
||||
@@ -1137,7 +1138,7 @@ namespace ts.FindAllReferences.Core {
|
||||
}
|
||||
}
|
||||
|
||||
function getContainingClassIfInHeritageClause(node: Node): ClassLikeDeclaration | InterfaceDeclaration {
|
||||
function getContainingClassIfInHeritageClause(node: Node): ClassLikeDeclaration | InterfaceDeclaration | undefined {
|
||||
return isIdentifier(node) || isPropertyAccessExpression(node) ? getContainingClassIfInHeritageClause(node.parent)
|
||||
: isExpressionWithTypeArguments(node) ? tryCast(node.parent.parent, isClassLike) : undefined;
|
||||
}
|
||||
@@ -1202,7 +1203,7 @@ namespace ts.FindAllReferences.Core {
|
||||
return inherits;
|
||||
}
|
||||
|
||||
function getReferencesForSuperKeyword(superKeyword: Node): SymbolAndEntries[] {
|
||||
function getReferencesForSuperKeyword(superKeyword: Node): SymbolAndEntries[] | undefined {
|
||||
let searchSpaceNode = getSuperContainer(superKeyword, /*stopOnFunctions*/ false);
|
||||
if (!searchSpaceNode) {
|
||||
return undefined;
|
||||
@@ -1242,7 +1243,7 @@ namespace ts.FindAllReferences.Core {
|
||||
return [{ definition: { type: "symbol", symbol: searchSpaceNode.symbol }, references }];
|
||||
}
|
||||
|
||||
function getReferencesForThisKeyword(thisOrSuperKeyword: Node, sourceFiles: ReadonlyArray<SourceFile>, cancellationToken: CancellationToken): SymbolAndEntries[] {
|
||||
function getReferencesForThisKeyword(thisOrSuperKeyword: Node, sourceFiles: ReadonlyArray<SourceFile>, cancellationToken: CancellationToken): SymbolAndEntries[] | undefined {
|
||||
let searchSpaceNode = getThisContainer(thisOrSuperKeyword, /* includeArrowFunctions */ false);
|
||||
|
||||
// Whether 'this' occurs in a static context within a class.
|
||||
@@ -1421,7 +1422,7 @@ namespace ts.FindAllReferences.Core {
|
||||
const type = checker.getTypeAtLocation(typeReference);
|
||||
const propertySymbol = type && type.symbol && checker.getPropertyOfType(type, propertyName);
|
||||
// Visit the typeReference as well to see if it directly or indirectly uses that property
|
||||
return propertySymbol && (firstDefined(checker.getRootSymbols(propertySymbol), cb) || recur(type.symbol));
|
||||
return propertySymbol && (firstDefined(checker.getRootSymbols(propertySymbol), cb) || recur(type!.symbol));
|
||||
}));
|
||||
}
|
||||
}
|
||||
@@ -1434,16 +1435,16 @@ namespace ts.FindAllReferences.Core {
|
||||
? rootSymbol && !(getCheckFlags(sym) & CheckFlags.Synthetic) ? rootSymbol : sym
|
||||
: undefined,
|
||||
/*allowBaseTypes*/ rootSymbol =>
|
||||
!(search.parents && !search.parents.some(parent => explicitlyInheritsFrom(rootSymbol.parent, parent, state.inheritsFromCache, checker))));
|
||||
!(search.parents && !search.parents.some(parent => explicitlyInheritsFrom(rootSymbol.parent!, parent, state.inheritsFromCache, checker))));
|
||||
}
|
||||
|
||||
/** Gets all symbols for one property. Does not get symbols for every property. */
|
||||
function getPropertySymbolsFromContextualType(node: ObjectLiteralElement, checker: TypeChecker): ReadonlyArray<Symbol> {
|
||||
const contextualType = checker.getContextualType(<ObjectLiteralExpression>node.parent);
|
||||
const name = getNameFromPropertyName(node.name);
|
||||
const name = getNameFromPropertyName(node.name!);
|
||||
const symbol = contextualType && name && contextualType.getProperty(name);
|
||||
return symbol ? [symbol] :
|
||||
contextualType && contextualType.isUnion() ? mapDefined(contextualType.types, t => t.getProperty(name)) : emptyArray;
|
||||
contextualType && contextualType.isUnion() ? mapDefined(contextualType.types, t => t.getProperty(name!)) : emptyArray; // TODO: GH#18217
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1489,11 +1490,11 @@ namespace ts.FindAllReferences.Core {
|
||||
}
|
||||
|
||||
export function getReferenceEntriesForShorthandPropertyAssignment(node: Node, checker: TypeChecker, addReference: (node: Node) => void): void {
|
||||
const refSymbol = checker.getSymbolAtLocation(node);
|
||||
const refSymbol = checker.getSymbolAtLocation(node)!;
|
||||
const shorthandSymbol = checker.getShorthandAssignmentValueSymbol(refSymbol.valueDeclaration);
|
||||
|
||||
if (shorthandSymbol) {
|
||||
for (const declaration of shorthandSymbol.getDeclarations()) {
|
||||
for (const declaration of shorthandSymbol.getDeclarations()!) {
|
||||
if (getMeaningFromDeclaration(declaration) & SemanticMeaning.Value) {
|
||||
addReference(declaration);
|
||||
}
|
||||
|
||||
@@ -14,9 +14,9 @@ namespace ts.formatting {
|
||||
}
|
||||
|
||||
export interface TokenInfo {
|
||||
leadingTrivia: TextRangeWithTriviaKind[];
|
||||
leadingTrivia: TextRangeWithTriviaKind[] | undefined;
|
||||
token: TextRangeWithKind;
|
||||
trailingTrivia: TextRangeWithTriviaKind[];
|
||||
trailingTrivia: TextRangeWithTriviaKind[] | undefined;
|
||||
}
|
||||
|
||||
const enum Constants {
|
||||
@@ -120,7 +120,7 @@ namespace ts.formatting {
|
||||
* and we wouldn't want to move the closing brace.
|
||||
*/
|
||||
const textRange: TextRange = {
|
||||
pos: getLineStartPositionForPosition(outermostNode.getStart(sourceFile), sourceFile),
|
||||
pos: getLineStartPositionForPosition(outermostNode!.getStart(sourceFile), sourceFile), // TODO: GH#18217
|
||||
end: position
|
||||
};
|
||||
|
||||
@@ -174,11 +174,11 @@ namespace ts.formatting {
|
||||
* Upon typing the closing curly, we want to format the entire `while`-statement, but not the preceding
|
||||
* variable declaration.
|
||||
*/
|
||||
function findOutermostNodeWithinListLevel(node: Node) {
|
||||
function findOutermostNodeWithinListLevel(node: Node | undefined) {
|
||||
let current = node;
|
||||
while (current &&
|
||||
current.parent &&
|
||||
current.parent.end === node.end &&
|
||||
current.parent.end === node!.end &&
|
||||
!isListElement(current.parent, current)) {
|
||||
current = current.parent;
|
||||
}
|
||||
@@ -195,7 +195,7 @@ namespace ts.formatting {
|
||||
return rangeContainsRange((<InterfaceDeclaration>parent).members, node);
|
||||
case SyntaxKind.ModuleDeclaration:
|
||||
const body = (<ModuleDeclaration>parent).body;
|
||||
return body && body.kind === SyntaxKind.ModuleBlock && rangeContainsRange(body.statements, node);
|
||||
return !!body && body.kind === SyntaxKind.ModuleBlock && rangeContainsRange(body.statements, node);
|
||||
case SyntaxKind.SourceFile:
|
||||
case SyntaxKind.Block:
|
||||
case SyntaxKind.ModuleBlock:
|
||||
@@ -235,8 +235,8 @@ namespace ts.formatting {
|
||||
|
||||
// pick only errors that fall in range
|
||||
const sorted = errors
|
||||
.filter(d => rangeOverlapsWithStartEnd(originalRange, d.start, d.start + d.length))
|
||||
.sort((e1, e2) => e1.start - e2.start);
|
||||
.filter(d => rangeOverlapsWithStartEnd(originalRange, d.start!, d.start! + d.length!)) // TODO: GH#18217
|
||||
.sort((e1, e2) => e1.start! - e2.start!);
|
||||
|
||||
if (!sorted.length) {
|
||||
return rangeHasNoErrors;
|
||||
@@ -254,12 +254,12 @@ namespace ts.formatting {
|
||||
}
|
||||
|
||||
const error = sorted[index];
|
||||
if (r.end <= error.start) {
|
||||
if (r.end <= error.start!) {
|
||||
// specified range ends before the error refered by 'index' - no error in range
|
||||
return false;
|
||||
}
|
||||
|
||||
if (startEndOverlapsWithStartEnd(r.pos, r.end, error.start, error.start + error.length)) {
|
||||
if (startEndOverlapsWithStartEnd(r.pos, r.end, error.start!, error.start! + error.length!)) {
|
||||
// specified range overlaps with error range
|
||||
return true;
|
||||
}
|
||||
@@ -316,7 +316,7 @@ namespace ts.formatting {
|
||||
*/
|
||||
function getOwnOrInheritedDelta(n: Node, options: FormatCodeSettings, sourceFile: SourceFile): number {
|
||||
let previousLine = Constants.Unknown;
|
||||
let child: Node;
|
||||
let child: Node | undefined;
|
||||
while (n) {
|
||||
const line = sourceFile.getLineAndCharacterOfPosition(n.getStart(sourceFile)).line;
|
||||
if (previousLine !== Constants.Unknown && line !== previousLine) {
|
||||
@@ -324,7 +324,7 @@ namespace ts.formatting {
|
||||
}
|
||||
|
||||
if (SmartIndenter.shouldIndentChildNode(options, n, child, sourceFile)) {
|
||||
return options.indentSize;
|
||||
return options.indentSize!;
|
||||
}
|
||||
|
||||
previousLine = line;
|
||||
@@ -349,7 +349,7 @@ namespace ts.formatting {
|
||||
sourceFileLike));
|
||||
}
|
||||
|
||||
function formatNodeLines(node: Node, sourceFile: SourceFile, formatContext: FormatContext, requestKind: FormattingRequestKind): TextChange[] {
|
||||
function formatNodeLines(node: Node | undefined, sourceFile: SourceFile, formatContext: FormatContext, requestKind: FormattingRequestKind): TextChange[] {
|
||||
if (!node) {
|
||||
return [];
|
||||
}
|
||||
@@ -413,7 +413,7 @@ namespace ts.formatting {
|
||||
if (!formattingScanner.isOnToken()) {
|
||||
const leadingTrivia = formattingScanner.getCurrentLeadingTrivia();
|
||||
if (leadingTrivia) {
|
||||
processTrivia(leadingTrivia, enclosingNode, enclosingNode, /*dynamicIndentation*/ undefined);
|
||||
processTrivia(leadingTrivia, enclosingNode, enclosingNode, /*dynamicIndentation*/ undefined!); // TODO: GH#18217
|
||||
trimTrailingWhitespacesForRemainingRange();
|
||||
}
|
||||
}
|
||||
@@ -465,7 +465,7 @@ namespace ts.formatting {
|
||||
parentDynamicIndentation: DynamicIndentation,
|
||||
effectiveParentStartLine: number
|
||||
): { indentation: number, delta: number } {
|
||||
const delta = SmartIndenter.shouldIndentChildNode(options, node) ? options.indentSize : 0;
|
||||
const delta = SmartIndenter.shouldIndentChildNode(options, node) ? options.indentSize! : 0;
|
||||
|
||||
if (effectiveParentStartLine === startLine) {
|
||||
// if node is located on the same line with the parent
|
||||
@@ -473,7 +473,7 @@ namespace ts.formatting {
|
||||
// - push children if either parent of node itself has non-zero delta
|
||||
return {
|
||||
indentation: startLine === lastIndentedLine ? indentationOnLastIndentedLine : parentDynamicIndentation.getIndentation(),
|
||||
delta: Math.min(options.indentSize, parentDynamicIndentation.getDelta(node) + delta)
|
||||
delta: Math.min(options.indentSize!, parentDynamicIndentation.getDelta(node) + delta)
|
||||
};
|
||||
}
|
||||
else if (inheritedIndentation === Constants.Unknown) {
|
||||
@@ -537,8 +537,8 @@ namespace ts.formatting {
|
||||
getDelta,
|
||||
recomputeIndentation: lineAdded => {
|
||||
if (node.parent && SmartIndenter.shouldIndentChildNode(options, node.parent, node, sourceFile)) {
|
||||
indentation += lineAdded ? options.indentSize : -options.indentSize;
|
||||
delta = SmartIndenter.shouldIndentChildNode(options, node) ? options.indentSize : 0;
|
||||
indentation += lineAdded ? options.indentSize! : -options.indentSize!;
|
||||
delta = SmartIndenter.shouldIndentChildNode(options, node) ? options.indentSize! : 0;
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -855,6 +855,7 @@ namespace ts.formatting {
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: GH#18217 use an enum instead of `boolean | undefined`
|
||||
function processRange(range: TextRangeWithKind,
|
||||
rangeStart: LineAndCharacter,
|
||||
parent: Node,
|
||||
@@ -934,7 +935,7 @@ namespace ts.formatting {
|
||||
return lineAction;
|
||||
}
|
||||
|
||||
function insertIndentation(pos: number, indentation: number, lineAdded: boolean): void {
|
||||
function insertIndentation(pos: number, indentation: number, lineAdded: boolean | undefined): void {
|
||||
const indentationString = getIndentationString(indentation, options);
|
||||
if (lineAdded) {
|
||||
// new line is added before the token by the formatting rules
|
||||
@@ -954,7 +955,7 @@ namespace ts.formatting {
|
||||
let column = 0;
|
||||
for (let i = 0; i < characterInLine; i++) {
|
||||
if (sourceFile.text.charCodeAt(startLinePosition + i) === CharacterCodes.tab) {
|
||||
column += options.tabSize - column % options.tabSize;
|
||||
column += options.tabSize! - column % options.tabSize!;
|
||||
}
|
||||
else {
|
||||
column++;
|
||||
@@ -1114,7 +1115,7 @@ namespace ts.formatting {
|
||||
// edit should not be applied if we have one line feed between elements
|
||||
const lineDelta = currentStartLine - previousStartLine;
|
||||
if (lineDelta !== 1) {
|
||||
recordReplace(previousRange.end, currentRange.pos - previousRange.end, options.newLineCharacter);
|
||||
recordReplace(previousRange.end, currentRange.pos - previousRange.end, options.newLineCharacter!);
|
||||
return onLaterLine ? LineAction.None : LineAction.LineAdded;
|
||||
}
|
||||
break;
|
||||
@@ -1231,8 +1232,8 @@ namespace ts.formatting {
|
||||
}
|
||||
|
||||
let internedSizes: { tabSize: number; indentSize: number };
|
||||
let internedTabsIndentation: string[];
|
||||
let internedSpacesIndentation: string[];
|
||||
let internedTabsIndentation: string[] | undefined;
|
||||
let internedSpacesIndentation: string[] | undefined;
|
||||
|
||||
export function getIndentationString(indentation: number, options: EditorSettings): string {
|
||||
// reset interned strings if FormatCodeOptions were changed
|
||||
@@ -1240,13 +1241,13 @@ namespace ts.formatting {
|
||||
!internedSizes || (internedSizes.tabSize !== options.tabSize || internedSizes.indentSize !== options.indentSize);
|
||||
|
||||
if (resetInternedStrings) {
|
||||
internedSizes = { tabSize: options.tabSize, indentSize: options.indentSize };
|
||||
internedSizes = { tabSize: options.tabSize!, indentSize: options.indentSize! };
|
||||
internedTabsIndentation = internedSpacesIndentation = undefined;
|
||||
}
|
||||
|
||||
if (!options.convertTabsToSpaces) {
|
||||
const tabs = Math.floor(indentation / options.tabSize);
|
||||
const spaces = indentation - tabs * options.tabSize;
|
||||
const tabs = Math.floor(indentation / options.tabSize!);
|
||||
const spaces = indentation - tabs * options.tabSize!;
|
||||
|
||||
let tabString: string;
|
||||
if (!internedTabsIndentation) {
|
||||
@@ -1264,14 +1265,14 @@ namespace ts.formatting {
|
||||
}
|
||||
else {
|
||||
let spacesString: string;
|
||||
const quotient = Math.floor(indentation / options.indentSize);
|
||||
const remainder = indentation % options.indentSize;
|
||||
const quotient = Math.floor(indentation / options.indentSize!);
|
||||
const remainder = indentation % options.indentSize!;
|
||||
if (!internedSpacesIndentation) {
|
||||
internedSpacesIndentation = [];
|
||||
}
|
||||
|
||||
if (internedSpacesIndentation[quotient] === undefined) {
|
||||
spacesString = repeatString(" ", options.indentSize * quotient);
|
||||
spacesString = repeatString(" ", options.indentSize! * quotient);
|
||||
internedSpacesIndentation[quotient] = spacesString;
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -16,11 +16,11 @@ namespace ts.formatting {
|
||||
public currentTokenParent: Node;
|
||||
public nextTokenParent: Node;
|
||||
|
||||
private contextNodeAllOnSameLine: boolean;
|
||||
private nextNodeAllOnSameLine: boolean;
|
||||
private tokensAreOnSameLine: boolean;
|
||||
private contextNodeBlockIsOnOneLine: boolean;
|
||||
private nextNodeBlockIsOnOneLine: boolean;
|
||||
private contextNodeAllOnSameLine: boolean | undefined;
|
||||
private nextNodeAllOnSameLine: boolean | undefined;
|
||||
private tokensAreOnSameLine: boolean | undefined;
|
||||
private contextNodeBlockIsOnOneLine: boolean | undefined;
|
||||
private nextNodeBlockIsOnOneLine: boolean | undefined;
|
||||
|
||||
constructor(public readonly sourceFile: SourceFileLike, public formattingRequestKind: FormattingRequestKind, public options: FormatCodeSettings) {
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ namespace ts.formatting {
|
||||
advance(): void;
|
||||
isOnToken(): boolean;
|
||||
readTokenInfo(n: Node): TokenInfo;
|
||||
getCurrentLeadingTrivia(): TextRangeWithKind[];
|
||||
getCurrentLeadingTrivia(): TextRangeWithKind[] | undefined;
|
||||
lastTrailingTriviaWasNewLine(): boolean;
|
||||
skipToEndOf(node: Node): void;
|
||||
}
|
||||
@@ -54,7 +54,7 @@ namespace ts.formatting {
|
||||
const isStarted = scanner.getStartPos() !== startPos;
|
||||
|
||||
if (isStarted) {
|
||||
wasNewLine = trailingTrivia && lastOrUndefined(trailingTrivia)!.kind === SyntaxKind.NewLineTrivia;
|
||||
wasNewLine = !!trailingTrivia && last(trailingTrivia).kind === SyntaxKind.NewLineTrivia;
|
||||
}
|
||||
else {
|
||||
scanner.scan();
|
||||
|
||||
@@ -677,7 +677,7 @@ namespace ts.formatting {
|
||||
|
||||
function isEndOfDecoratorContextOnSameLine(context: FormattingContext): boolean {
|
||||
return context.TokensAreOnSameLine() &&
|
||||
context.contextNode.decorators &&
|
||||
!!context.contextNode.decorators &&
|
||||
nodeIsInDecoratorContext(context.currentTokenParent) &&
|
||||
!nodeIsInDecoratorContext(context.nextTokenParent);
|
||||
}
|
||||
|
||||
@@ -111,6 +111,7 @@ namespace ts.formatting {
|
||||
// if such node is found - compute initial indentation for 'position' inside this node
|
||||
let previous: Node | undefined;
|
||||
let current = precedingToken;
|
||||
|
||||
while (current) {
|
||||
if (positionBelongsToNode(current, position, sourceFile) && shouldIndentChildNode(options, current, previous, sourceFile, /*isNextChild*/ true)) {
|
||||
const currentStart = getStartLineAndCharacterForNode(current, sourceFile);
|
||||
@@ -119,7 +120,7 @@ namespace ts.formatting {
|
||||
// handle cases when codefix is about to be inserted before the close brace
|
||||
? assumeNewLineBeforeCloseBrace && nextTokenKind === NextTokenKind.CloseBrace ? options.indentSize : 0
|
||||
: lineAtPosition !== currentStart.line ? options.indentSize : 0;
|
||||
return getIndentationForNodeWorker(current, currentStart, /*ignoreActualIndentationRange*/ undefined, indentationDelta, sourceFile, /*isNextChild*/ true, options);
|
||||
return getIndentationForNodeWorker(current, currentStart, /*ignoreActualIndentationRange*/ undefined, indentationDelta!, sourceFile, /*isNextChild*/ true, options); // TODO: GH#18217
|
||||
}
|
||||
|
||||
// check if current node is a list item - if yes, take indentation from it
|
||||
@@ -129,7 +130,7 @@ namespace ts.formatting {
|
||||
}
|
||||
actualIndentation = getLineIndentationWhenExpressionIsInMultiLine(current, sourceFile, options);
|
||||
if (actualIndentation !== Value.Unknown) {
|
||||
return actualIndentation + options.indentSize;
|
||||
return actualIndentation + options.indentSize!; // TODO: GH#18217
|
||||
}
|
||||
|
||||
previous = current;
|
||||
@@ -151,12 +152,13 @@ namespace ts.formatting {
|
||||
function getIndentationForNodeWorker(
|
||||
current: Node,
|
||||
currentStart: LineAndCharacter,
|
||||
ignoreActualIndentationRange: TextRange,
|
||||
ignoreActualIndentationRange: TextRange | undefined,
|
||||
indentationDelta: number,
|
||||
sourceFile: SourceFile,
|
||||
isNextChild: boolean,
|
||||
options: EditorSettings): number {
|
||||
let parent = current.parent!;
|
||||
let parent = current.parent;
|
||||
|
||||
// Walk up the tree and collect indentation for parent-child node pairs. Indentation is not added if
|
||||
// * parent and child nodes start on the same line, or
|
||||
// * parent is an IfStatement and child starts on the same line as an 'else clause'.
|
||||
@@ -194,7 +196,7 @@ namespace ts.formatting {
|
||||
|
||||
// increase indentation if parent node wants its content to be indented and parent and child nodes don't start on the same line
|
||||
if (shouldIndentChildNode(options, parent, current, sourceFile, isNextChild) && !parentAndChildShareLine) {
|
||||
indentationDelta += options.indentSize;
|
||||
indentationDelta += options.indentSize!;
|
||||
}
|
||||
|
||||
// In our AST, a call argument's `parent` is the call-expression, not the argument list.
|
||||
@@ -311,7 +313,7 @@ namespace ts.formatting {
|
||||
|
||||
export function childStartsOnTheSameLineWithElseInIfStatement(parent: Node, child: TextRangeWithKind, childStartLine: number, sourceFile: SourceFileLike): boolean {
|
||||
if (parent.kind === SyntaxKind.IfStatement && (<IfStatement>parent).elseStatement === child) {
|
||||
const elseKeyword = findChildOfKind(parent, SyntaxKind.ElseKeyword, sourceFile);
|
||||
const elseKeyword = findChildOfKind(parent, SyntaxKind.ElseKeyword, sourceFile)!;
|
||||
Debug.assert(elseKeyword !== undefined);
|
||||
|
||||
const elseKeywordStartLine = getStartLineAndCharacterForNode(elseKeyword, sourceFile).line;
|
||||
@@ -321,11 +323,11 @@ namespace ts.formatting {
|
||||
return false;
|
||||
}
|
||||
|
||||
function getListIfStartEndIsInListRange(list: NodeArray<Node>, start: number, end: number) {
|
||||
function getListIfStartEndIsInListRange(list: NodeArray<Node> | undefined, start: number, end: number) {
|
||||
return list && rangeContainsStartEnd(list, start, end) ? list : undefined;
|
||||
}
|
||||
|
||||
export function getContainingList(node: Node, sourceFile: SourceFile): NodeArray<Node> {
|
||||
export function getContainingList(node: Node, sourceFile: SourceFile): NodeArray<Node> | undefined {
|
||||
if (node.parent) {
|
||||
const { end } = node;
|
||||
switch (node.parent.kind) {
|
||||
@@ -467,7 +469,7 @@ namespace ts.formatting {
|
||||
}
|
||||
|
||||
if (ch === CharacterCodes.tab) {
|
||||
column += options.tabSize + (column % options.tabSize);
|
||||
column += options.tabSize! + (column % options.tabSize!);
|
||||
}
|
||||
else {
|
||||
column++;
|
||||
@@ -482,7 +484,7 @@ namespace ts.formatting {
|
||||
return findFirstNonWhitespaceCharacterAndColumn(startPos, endPos, sourceFile, options).column;
|
||||
}
|
||||
|
||||
export function nodeWillIndentChild(settings: FormatCodeSettings | undefined, parent: TextRangeWithKind, child: TextRangeWithKind | undefined, sourceFile: SourceFileLike | undefined, indentByDefault: boolean): boolean {
|
||||
export function nodeWillIndentChild(settings: FormatCodeSettings, parent: TextRangeWithKind, child: TextRangeWithKind | undefined, sourceFile: SourceFileLike | undefined, indentByDefault: boolean): boolean {
|
||||
const childKind = child ? child.kind : SyntaxKind.Unknown;
|
||||
|
||||
switch (parent.kind) {
|
||||
@@ -533,8 +535,8 @@ namespace ts.formatting {
|
||||
return true;
|
||||
case SyntaxKind.VariableDeclaration:
|
||||
case SyntaxKind.PropertyAssignment:
|
||||
if (!settings.indentMultiLineObjectLiteralBeginningOnBlankLine && sourceFile && childKind === SyntaxKind.ObjectLiteralExpression) {
|
||||
return rangeIsOnOneLine(sourceFile, child);
|
||||
if (!settings.indentMultiLineObjectLiteralBeginningOnBlankLine && sourceFile && childKind === SyntaxKind.ObjectLiteralExpression) { // TODO: GH#18217
|
||||
return rangeIsOnOneLine(sourceFile, child!);
|
||||
}
|
||||
return true;
|
||||
case SyntaxKind.DoStatement:
|
||||
@@ -555,7 +557,7 @@ namespace ts.formatting {
|
||||
return childKind !== SyntaxKind.NamedExports;
|
||||
case SyntaxKind.ImportDeclaration:
|
||||
return childKind !== SyntaxKind.ImportClause ||
|
||||
(!!(<ImportClause>child).namedBindings && (<ImportClause>child).namedBindings.kind !== SyntaxKind.NamedImports);
|
||||
(!!(<ImportClause>child).namedBindings && (<ImportClause>child).namedBindings!.kind !== SyntaxKind.NamedImports);
|
||||
case SyntaxKind.JsxElement:
|
||||
return childKind !== SyntaxKind.JsxClosingElement;
|
||||
case SyntaxKind.JsxFragment:
|
||||
@@ -594,7 +596,7 @@ namespace ts.formatting {
|
||||
* True when the parent node should indent the given child by an explicit rule.
|
||||
* @param isNextChild If true, we are judging indent of a hypothetical child *after* this one, not the current child.
|
||||
*/
|
||||
export function shouldIndentChildNode(settings: FormatCodeSettings | undefined, parent: TextRangeWithKind, child?: Node, sourceFile?: SourceFileLike, isNextChild = false): boolean {
|
||||
export function shouldIndentChildNode(settings: FormatCodeSettings, parent: TextRangeWithKind, child?: Node, sourceFile?: SourceFileLike, isNextChild = false): boolean {
|
||||
return nodeWillIndentChild(settings, parent, child, sourceFile, /*indentByDefault*/ false)
|
||||
&& !(isNextChild && child && isControlFlowEndingStatement(child.kind, parent));
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@ namespace ts {
|
||||
|
||||
function updateTsconfigFiles(program: Program, changeTracker: textChanges.ChangeTracker, oldFilePath: string, newFilePath: string): void {
|
||||
const configFile = program.getCompilerOptions().configFile;
|
||||
if (!configFile) return;
|
||||
const oldFile = getTsConfigPropArrayElementValue(configFile, "files", oldFilePath);
|
||||
if (oldFile) {
|
||||
changeTracker.replaceRangeWithText(configFile, createStringRange(oldFile, configFile), newFilePath);
|
||||
|
||||
@@ -10,11 +10,12 @@ namespace ts.GoToDefinition {
|
||||
if (node === sourceFile) {
|
||||
return undefined;
|
||||
}
|
||||
const { parent } = node;
|
||||
|
||||
// Labels
|
||||
if (isJumpStatementTarget(node)) {
|
||||
const label = getTargetLabel(node.parent, node.text);
|
||||
return label ? [createDefinitionInfoFromName(label, ScriptElementKind.label, node.text, /*containerName*/ undefined)] : undefined;
|
||||
return label ? [createDefinitionInfoFromName(label, ScriptElementKind.label, node.text, /*containerName*/ undefined!)] : undefined; // TODO: GH#18217
|
||||
}
|
||||
|
||||
const typeChecker = program.getTypeChecker();
|
||||
@@ -33,9 +34,9 @@ namespace ts.GoToDefinition {
|
||||
// If this is the original constructor definition, parent is the class.
|
||||
return typeChecker.getRootSymbols(symbol).some(s => calledDeclaration.symbol === s || calledDeclaration.symbol.parent === s) ||
|
||||
// TODO: GH#23742 Following check shouldn't be necessary if 'require' is an alias
|
||||
symbol.declarations.some(d => isVariableDeclaration(d) && d.initializer && isRequireCall(d.initializer, /*checkArgumentIsStringLiteralLike*/ false))
|
||||
symbol.declarations.some(d => isVariableDeclaration(d) && !!d.initializer && isRequireCall(d.initializer, /*checkArgumentIsStringLiteralLike*/ false))
|
||||
? [sigInfo]
|
||||
: [sigInfo, ...getDefinitionFromSymbol(typeChecker, symbol, node)];
|
||||
: [sigInfo, ...getDefinitionFromSymbol(typeChecker, symbol, node)!];
|
||||
}
|
||||
|
||||
// Because name in short-hand property assignment has two different meanings: property name and property value,
|
||||
@@ -59,9 +60,9 @@ namespace ts.GoToDefinition {
|
||||
// pr/*destination*/op1: number
|
||||
// }
|
||||
// bar<Test>(({pr/*goto*/op1})=>{});
|
||||
if (isPropertyName(node) && isBindingElement(node.parent) && isObjectBindingPattern(node.parent.parent) &&
|
||||
(node === (node.parent.propertyName || node.parent.name))) {
|
||||
const type = typeChecker.getTypeAtLocation(node.parent.parent);
|
||||
if (isPropertyName(node) && isBindingElement(parent) && isObjectBindingPattern(parent.parent) &&
|
||||
(node === (parent.propertyName || parent.name))) {
|
||||
const type = typeChecker.getTypeAtLocation(parent.parent);
|
||||
if (type) {
|
||||
const propSymbols = getPropertySymbolsFromType(type, node);
|
||||
if (propSymbols) {
|
||||
@@ -97,7 +98,7 @@ namespace ts.GoToDefinition {
|
||||
const typeReferenceDirective = findReferenceInPosition(sourceFile.typeReferenceDirectives, position);
|
||||
if (typeReferenceDirective) {
|
||||
const reference = program.getResolvedTypeReferenceDirectives().get(typeReferenceDirective.fileName);
|
||||
const file = reference && program.getSourceFile(reference.resolvedFileName);
|
||||
const file = reference && program.getSourceFile(reference.resolvedFileName!); // TODO:GH#18217
|
||||
return file && { fileName: typeReferenceDirective.fileName, file };
|
||||
}
|
||||
|
||||
@@ -105,7 +106,7 @@ namespace ts.GoToDefinition {
|
||||
}
|
||||
|
||||
/// Goto type
|
||||
export function getTypeDefinitionAtPosition(typeChecker: TypeChecker, sourceFile: SourceFile, position: number): DefinitionInfo[] {
|
||||
export function getTypeDefinitionAtPosition(typeChecker: TypeChecker, sourceFile: SourceFile, position: number): DefinitionInfo[] | undefined {
|
||||
const node = getTouchingPropertyName(sourceFile, position, /*includeJsDocComment*/ true);
|
||||
if (node === sourceFile) {
|
||||
return undefined;
|
||||
@@ -124,7 +125,7 @@ namespace ts.GoToDefinition {
|
||||
return type.symbol && getDefinitionFromSymbol(typeChecker, type.symbol, node);
|
||||
}
|
||||
|
||||
export function getDefinitionAndBoundSpan(program: Program, sourceFile: SourceFile, position: number): DefinitionInfoAndBoundSpan {
|
||||
export function getDefinitionAndBoundSpan(program: Program, sourceFile: SourceFile, position: number): DefinitionInfoAndBoundSpan | undefined {
|
||||
const definitions = getDefinitionAtPosition(program, sourceFile, position);
|
||||
|
||||
if (!definitions || definitions.length === 0) {
|
||||
@@ -146,7 +147,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);
|
||||
@@ -191,7 +192,7 @@ namespace ts.GoToDefinition {
|
||||
}
|
||||
}
|
||||
|
||||
function getDefinitionFromSymbol(typeChecker: TypeChecker, symbol: Symbol, node: Node): DefinitionInfo[] {
|
||||
function getDefinitionFromSymbol(typeChecker: TypeChecker, symbol: Symbol, node: Node): DefinitionInfo[] | undefined {
|
||||
return getConstructSignatureDefinition() || getCallSignatureDefinition() || map(symbol.declarations, declaration => createDefinitionInfo(declaration, typeChecker, symbol, node));
|
||||
|
||||
function getConstructSignatureDefinition(): DefinitionInfo[] | undefined {
|
||||
@@ -237,7 +238,7 @@ namespace ts.GoToDefinition {
|
||||
textSpan: createTextSpanFromNode(name, sourceFile),
|
||||
kind: symbolKind,
|
||||
name: symbolName,
|
||||
containerKind: undefined,
|
||||
containerKind: undefined!, // TODO: GH#18217
|
||||
containerName
|
||||
};
|
||||
}
|
||||
@@ -256,8 +257,8 @@ namespace ts.GoToDefinition {
|
||||
textSpan: createTextSpanFromBounds(0, 0),
|
||||
kind: ScriptElementKind.scriptElement,
|
||||
name,
|
||||
containerName: undefined,
|
||||
containerKind: undefined
|
||||
containerName: undefined!,
|
||||
containerKind: undefined!, // TODO: GH#18217
|
||||
};
|
||||
}
|
||||
|
||||
@@ -265,7 +266,7 @@ namespace ts.GoToDefinition {
|
||||
function getAncestorCallLikeExpression(node: Node): CallLikeExpression | undefined {
|
||||
const target = climbPastManyPropertyAccesses(node);
|
||||
const callLike = target.parent;
|
||||
return callLike && isCallLikeExpression(callLike) && getInvokedExpression(callLike) === target && callLike;
|
||||
return callLike && isCallLikeExpression(callLike) && getInvokedExpression(callLike) === target ? callLike : undefined;
|
||||
}
|
||||
|
||||
function climbPastManyPropertyAccesses(node: Node): Node {
|
||||
|
||||
@@ -49,7 +49,7 @@ namespace ts.FindAllReferences {
|
||||
const markSeenIndirectUser = nodeSeenTracker<SourceFileLike>();
|
||||
const directImports: Importer[] = [];
|
||||
const isAvailableThroughGlobal = !!exportingModuleSymbol.globalExports;
|
||||
const indirectUserDeclarations: SourceFileLike[] = isAvailableThroughGlobal ? undefined : [];
|
||||
const indirectUserDeclarations: SourceFileLike[] | undefined = isAvailableThroughGlobal ? undefined : [];
|
||||
|
||||
handleDirectImports(exportingModuleSymbol);
|
||||
|
||||
@@ -69,7 +69,7 @@ namespace ts.FindAllReferences {
|
||||
}
|
||||
|
||||
// This may return duplicates (if there are multiple module declarations in a single source file, all importing the same thing as a namespace), but `State.markSearchedSymbol` will handle that.
|
||||
return indirectUserDeclarations.map(getSourceFileOfNode);
|
||||
return indirectUserDeclarations!.map<SourceFile>(getSourceFileOfNode);
|
||||
}
|
||||
|
||||
function handleDirectImports(exportingModuleSymbol: Symbol): void {
|
||||
@@ -85,7 +85,7 @@ namespace ts.FindAllReferences {
|
||||
switch (direct.kind) {
|
||||
case SyntaxKind.CallExpression:
|
||||
if (!isAvailableThroughGlobal) {
|
||||
const parent = direct.parent!;
|
||||
const parent = direct.parent;
|
||||
if (exportKind === ExportKind.ExportEquals && parent.kind === SyntaxKind.VariableDeclaration) {
|
||||
const { name } = parent as VariableDeclaration;
|
||||
if (name.kind === SyntaxKind.Identifier) {
|
||||
@@ -166,7 +166,7 @@ namespace ts.FindAllReferences {
|
||||
Debug.assert(!isAvailableThroughGlobal);
|
||||
const isNew = markSeenIndirectUser(sourceFileLike);
|
||||
if (isNew) {
|
||||
indirectUserDeclarations.push(sourceFileLike);
|
||||
indirectUserDeclarations!.push(sourceFileLike); // TODO: GH#18217
|
||||
}
|
||||
return isNew;
|
||||
}
|
||||
@@ -238,7 +238,7 @@ namespace ts.FindAllReferences {
|
||||
}
|
||||
|
||||
// Ignore if there's a grammar error
|
||||
if (decl.moduleSpecifier.kind !== SyntaxKind.StringLiteral) {
|
||||
if (decl.moduleSpecifier!.kind !== SyntaxKind.StringLiteral) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -259,7 +259,7 @@ namespace ts.FindAllReferences {
|
||||
}
|
||||
|
||||
if (exportKind === ExportKind.Named) {
|
||||
searchForNamedImport(namedBindings as NamedImports | undefined);
|
||||
searchForNamedImport(namedBindings as NamedImports | undefined); // tslint:disable-line no-unnecessary-type-assertion (TODO: GH#18217)
|
||||
}
|
||||
else {
|
||||
// `export =` might be imported by a default import if `--allowSyntheticDefaultImports` is on, so this handles both ExportKind.Default and ExportKind.ExportEquals
|
||||
@@ -267,13 +267,13 @@ namespace ts.FindAllReferences {
|
||||
// If a default import has the same name as the default export, allow to rename it.
|
||||
// Given `import f` and `export default function f`, we will rename both, but for `import g` we will rename just that.
|
||||
if (name && (!isForRename || name.escapedText === symbolEscapedNameNoDefault(exportSymbol))) {
|
||||
const defaultImportAlias = checker.getSymbolAtLocation(name);
|
||||
const defaultImportAlias = checker.getSymbolAtLocation(name)!;
|
||||
addSearch(name, defaultImportAlias);
|
||||
}
|
||||
|
||||
// 'default' might be accessed as a named import `{ default as foo }`.
|
||||
if (exportKind === ExportKind.Default) {
|
||||
searchForNamedImport(namedBindings as NamedImports | undefined);
|
||||
searchForNamedImport(namedBindings);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -286,7 +286,7 @@ namespace ts.FindAllReferences {
|
||||
function handleNamespaceImportLike(importName: Identifier): void {
|
||||
// Don't rename an import that already has a different name than the export.
|
||||
if (exportKind === ExportKind.ExportEquals && (!isForRename || isNameMatch(importName.escapedText))) {
|
||||
addSearch(importName, checker.getSymbolAtLocation(importName));
|
||||
addSearch(importName, checker.getSymbolAtLocation(importName)!);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -308,13 +308,13 @@ namespace ts.FindAllReferences {
|
||||
// But do rename `foo` in ` { default as foo }` if that's the original export name.
|
||||
if (!isForRename || name.escapedText === exportSymbol.escapedName) {
|
||||
// Search locally for `bar`.
|
||||
addSearch(name, checker.getSymbolAtLocation(name));
|
||||
addSearch(name, checker.getSymbolAtLocation(name)!);
|
||||
}
|
||||
}
|
||||
else {
|
||||
const localSymbol = element.kind === SyntaxKind.ExportSpecifier && element.propertyName
|
||||
? checker.getExportSpecifierLocalTargetSymbol(element) // For re-exporting under a different name, we want to get the re-exported symbol.
|
||||
: checker.getSymbolAtLocation(name);
|
||||
? checker.getExportSpecifierLocalTargetSymbol(element)! // For re-exporting under a different name, we want to get the re-exported symbol.
|
||||
: checker.getSymbolAtLocation(name)!;
|
||||
addSearch(name, localSymbol);
|
||||
}
|
||||
}
|
||||
@@ -330,7 +330,7 @@ namespace ts.FindAllReferences {
|
||||
function findNamespaceReExports(sourceFileLike: SourceFileLike, name: Identifier, checker: TypeChecker): boolean {
|
||||
const namespaceImportSymbol = checker.getSymbolAtLocation(name);
|
||||
|
||||
return forEachPossibleImportOrExportStatement(sourceFileLike, statement => {
|
||||
return !!forEachPossibleImportOrExportStatement(sourceFileLike, statement => {
|
||||
if (!isExportDeclaration(statement)) return;
|
||||
const { exportClause, moduleSpecifier } = statement;
|
||||
return !moduleSpecifier && exportClause &&
|
||||
@@ -395,8 +395,8 @@ namespace ts.FindAllReferences {
|
||||
}
|
||||
|
||||
/** Iterates over all statements at the top level or in module declarations. Returns the first truthy result. */
|
||||
function forEachPossibleImportOrExportStatement<T>(sourceFileLike: SourceFileLike, action: (statement: Statement) => T): T {
|
||||
return forEach(sourceFileLike.kind === SyntaxKind.SourceFile ? sourceFileLike.statements : sourceFileLike.body.statements, statement =>
|
||||
function forEachPossibleImportOrExportStatement<T>(sourceFileLike: SourceFileLike, action: (statement: Statement) => T): T | undefined {
|
||||
return forEach(sourceFileLike.kind === SyntaxKind.SourceFile ? sourceFileLike.statements : sourceFileLike.body!.statements, statement => // TODO: GH#18217
|
||||
action(statement) || (isAmbientModuleDeclaration(statement) && forEach(statement.body && statement.body.statements, action)));
|
||||
}
|
||||
|
||||
@@ -453,13 +453,14 @@ namespace ts.FindAllReferences {
|
||||
return comingFromExport ? getExport() : getExport() || getImport();
|
||||
|
||||
function getExport(): ExportedSymbol | ImportedSymbol | undefined {
|
||||
const parent = node.parent!;
|
||||
const { parent } = node;
|
||||
const grandParent = parent.parent;
|
||||
if (symbol.exportSymbol) {
|
||||
if (parent.kind === SyntaxKind.PropertyAccessExpression) {
|
||||
// When accessing an export of a JS module, there's no alias. The symbol will still be flagged as an export even though we're at the use.
|
||||
// So check that we are at the declaration.
|
||||
return symbol.declarations.some(d => d === parent) && isBinaryExpression(parent.parent)
|
||||
? getSpecialPropertyExport(parent.parent, /*useLhsSymbol*/ false)
|
||||
return symbol.declarations.some(d => d === parent) && isBinaryExpression(grandParent)
|
||||
? getSpecialPropertyExport(grandParent, /*useLhsSymbol*/ false)
|
||||
: undefined;
|
||||
}
|
||||
else {
|
||||
@@ -475,7 +476,7 @@ namespace ts.FindAllReferences {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const lhsSymbol = checker.getSymbolAtLocation(exportNode.name);
|
||||
const lhsSymbol = checker.getSymbolAtLocation(exportNode.name)!;
|
||||
return { kind: ImportExport.Import, symbol: lhsSymbol, isNamedImport: false };
|
||||
}
|
||||
else {
|
||||
@@ -487,15 +488,15 @@ namespace ts.FindAllReferences {
|
||||
return getExportAssignmentExport(parent);
|
||||
}
|
||||
// If we are in `export = class A {};` (or `export = class A {};`) at `A`, `parent.parent` is the export assignment.
|
||||
else if (isExportAssignment(parent.parent)) {
|
||||
return getExportAssignmentExport(parent.parent);
|
||||
else if (isExportAssignment(grandParent)) {
|
||||
return getExportAssignmentExport(grandParent);
|
||||
}
|
||||
// Similar for `module.exports =` and `exports.A =`.
|
||||
else if (isBinaryExpression(parent)) {
|
||||
return getSpecialPropertyExport(parent, /*useLhsSymbol*/ true);
|
||||
}
|
||||
else if (isBinaryExpression(parent.parent)) {
|
||||
return getSpecialPropertyExport(parent.parent, /*useLhsSymbol*/ true);
|
||||
else if (isBinaryExpression(grandParent)) {
|
||||
return getSpecialPropertyExport(grandParent, /*useLhsSymbol*/ true);
|
||||
}
|
||||
else if (isJSDocTypedefTag(parent)) {
|
||||
return exportInfo(symbol, ExportKind.Named);
|
||||
@@ -524,8 +525,8 @@ namespace ts.FindAllReferences {
|
||||
|
||||
const sym = useLhsSymbol ? checker.getSymbolAtLocation(cast(node.left, isPropertyAccessExpression).name) : symbol;
|
||||
// Better detection for GH#20803
|
||||
if (sym && !(checker.getMergedSymbol(sym.parent).flags & SymbolFlags.Module)) {
|
||||
Debug.fail(`Special property assignment kind does not have a module as its parent. Assignment is ${Debug.showSymbol(sym)}, parent is ${Debug.showSymbol(sym.parent)}`);
|
||||
if (sym && !(checker.getMergedSymbol(sym.parent!).flags & SymbolFlags.Module)) {
|
||||
Debug.fail(`Special property assignment kind does not have a module as its parent. Assignment is ${Debug.showSymbol(sym)}, parent is ${Debug.showSymbol(sym.parent!)}`);
|
||||
}
|
||||
return sym && exportInfo(sym, kind);
|
||||
}
|
||||
@@ -555,13 +556,13 @@ namespace ts.FindAllReferences {
|
||||
}
|
||||
}
|
||||
|
||||
function exportInfo(symbol: Symbol, kind: ExportKind): ExportedSymbol {
|
||||
function exportInfo(symbol: Symbol, kind: ExportKind): ExportedSymbol | undefined {
|
||||
const exportInfo = getExportInfo(symbol, kind, checker);
|
||||
return exportInfo && { kind: ImportExport.Export, symbol, exportInfo };
|
||||
}
|
||||
|
||||
// Not meant for use with export specifiers or export assignment.
|
||||
function getExportKindForDeclaration(node: Node): ExportKind | undefined {
|
||||
function getExportKindForDeclaration(node: Node): ExportKind {
|
||||
return hasModifier(node, ModifierFlags.Default) ? ExportKind.Default : ExportKind.Named;
|
||||
}
|
||||
}
|
||||
@@ -627,7 +628,7 @@ namespace ts.FindAllReferences {
|
||||
if (symbol.declarations) {
|
||||
for (const declaration of symbol.declarations) {
|
||||
if (isExportSpecifier(declaration) && !declaration.propertyName && !declaration.parent.parent.moduleSpecifier) {
|
||||
return checker.getExportSpecifierLocalTargetSymbol(declaration);
|
||||
return checker.getExportSpecifierLocalTargetSymbol(declaration)!;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -644,7 +645,6 @@ namespace ts.FindAllReferences {
|
||||
}
|
||||
|
||||
const { parent } = node;
|
||||
|
||||
if (parent.kind === SyntaxKind.SourceFile) {
|
||||
return parent as SourceFile;
|
||||
}
|
||||
|
||||
@@ -99,7 +99,7 @@ namespace ts.JsDoc {
|
||||
case SyntaxKind.JSDocTemplateTag:
|
||||
return withList((tag as JSDocTemplateTag).typeParameters);
|
||||
case SyntaxKind.JSDocTypeTag:
|
||||
return withNode((tag as JSDocTypeTag).typeExpression);
|
||||
return withNode((tag as JSDocTypeTag).typeExpression!);
|
||||
case SyntaxKind.JSDocTypedefTag:
|
||||
case SyntaxKind.JSDocCallbackTag:
|
||||
case SyntaxKind.JSDocPropertyTag:
|
||||
@@ -128,7 +128,7 @@ namespace ts.JsDoc {
|
||||
* returns a truthy value, then returns that value.
|
||||
* If no such value is found, the callback is applied to each element of array and undefined is returned.
|
||||
*/
|
||||
function forEachUnique<T, U>(array: ReadonlyArray<T>, callback: (element: T, index: number) => U): U {
|
||||
function forEachUnique<T, U>(array: ReadonlyArray<T> | undefined, callback: (element: T, index: number) => U): U | undefined {
|
||||
if (array) {
|
||||
for (let i = 0; i < array.length; i++) {
|
||||
if (array.indexOf(array[i]) === i) {
|
||||
@@ -191,7 +191,7 @@ namespace ts.JsDoc {
|
||||
if (!isIdentifier(param.name)) return undefined;
|
||||
|
||||
const name = param.name.text;
|
||||
if (jsdoc.tags.some(t => t !== tag && isJSDocParameterTag(t) && isIdentifier(t.name) && t.name.escapedText === name)
|
||||
if (jsdoc.tags!.some(t => t !== tag && isJSDocParameterTag(t) && isIdentifier(t.name) && t.name.escapedText === name) // TODO: GH#18217
|
||||
|| nameThusFar !== undefined && !startsWith(name, nameThusFar)) {
|
||||
return undefined;
|
||||
}
|
||||
@@ -326,7 +326,7 @@ namespace ts.JsDoc {
|
||||
const varStatement = <VariableStatement>commentOwner;
|
||||
const varDeclarations = varStatement.declarationList.declarations;
|
||||
const parameters = varDeclarations.length === 1 && varDeclarations[0].initializer
|
||||
? getParametersFromRightHandSideOfAssignment(varDeclarations[0].initializer)
|
||||
? getParametersFromRightHandSideOfAssignment(varDeclarations[0].initializer!)
|
||||
: undefined;
|
||||
return { commentOwner, parameters };
|
||||
}
|
||||
@@ -371,7 +371,7 @@ namespace ts.JsDoc {
|
||||
return (<FunctionExpression>rightHandSide).parameters;
|
||||
case SyntaxKind.ClassExpression: {
|
||||
const ctr = find((rightHandSide as ClassExpression).members, isConstructorDeclaration);
|
||||
return ctr && ctr.parameters;
|
||||
return ctr ? ctr.parameters : emptyArray;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ namespace ts.JsTyping {
|
||||
directoryExists(path: string): boolean;
|
||||
fileExists(fileName: string): boolean;
|
||||
readFile(path: string, encoding?: string): string | undefined;
|
||||
readDirectory(rootDir: string, extensions: ReadonlyArray<string>, excludes: ReadonlyArray<string>, includes: ReadonlyArray<string>, depth?: number): string[];
|
||||
readDirectory(rootDir: string, extensions: ReadonlyArray<string>, excludes: ReadonlyArray<string> | undefined, includes: ReadonlyArray<string> | undefined, depth?: number): string[];
|
||||
}
|
||||
|
||||
interface PackageJson {
|
||||
@@ -26,7 +26,7 @@ namespace ts.JsTyping {
|
||||
|
||||
/* @internal */
|
||||
export function isTypingUpToDate(cachedTyping: CachedTyping, availableTypingVersions: MapLike<string>) {
|
||||
const availableVersion = Semver.parse(getProperty(availableTypingVersions, `ts${versionMajorMinor}`) || getProperty(availableTypingVersions, "latest"));
|
||||
const availableVersion = Semver.parse(getProperty(availableTypingVersions, `ts${versionMajorMinor}`) || getProperty(availableTypingVersions, "latest")!);
|
||||
return !availableVersion.greaterThan(cachedTyping.version);
|
||||
}
|
||||
|
||||
@@ -152,7 +152,7 @@ namespace ts.JsTyping {
|
||||
|
||||
// add typings for unresolved imports
|
||||
if (unresolvedImports) {
|
||||
const module = deduplicate(
|
||||
const module = deduplicate<string>(
|
||||
unresolvedImports.map(moduleId => nodeCoreModules.has(moduleId) ? "node" : moduleId),
|
||||
equateStringsCaseSensitive,
|
||||
compareStringsCaseSensitive);
|
||||
@@ -160,7 +160,7 @@ namespace ts.JsTyping {
|
||||
}
|
||||
// Add the cached typing locations for inferred typings that are already installed
|
||||
packageNameToTypingLocation.forEach((typing, name) => {
|
||||
if (inferredTypings.has(name) && inferredTypings.get(name) === undefined && isTypingUpToDate(typing, typesRegistry.get(name))) {
|
||||
if (inferredTypings.has(name) && inferredTypings.get(name) === undefined && isTypingUpToDate(typing, typesRegistry.get(name)!)) {
|
||||
inferredTypings.set(name, typing.typingLocation);
|
||||
}
|
||||
});
|
||||
@@ -187,7 +187,7 @@ namespace ts.JsTyping {
|
||||
|
||||
function addInferredTyping(typingName: string) {
|
||||
if (!inferredTypings.has(typingName)) {
|
||||
inferredTypings.set(typingName, undefined);
|
||||
inferredTypings.set(typingName, undefined!); // TODO: GH#18217
|
||||
}
|
||||
}
|
||||
function addInferredTypings(typingNames: ReadonlyArray<string>, message: string) {
|
||||
@@ -344,7 +344,7 @@ namespace ts.JsTyping {
|
||||
case PackageNameValidationResult.Ok:
|
||||
return Debug.fail(); // Shouldn't have called this.
|
||||
default:
|
||||
Debug.assertNever(result);
|
||||
throw Debug.assertNever(result);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ namespace ts.NavigateTo {
|
||||
declaration: Declaration;
|
||||
}
|
||||
|
||||
export function getNavigateToItems(sourceFiles: ReadonlyArray<SourceFile>, checker: TypeChecker, cancellationToken: CancellationToken, searchValue: string, maxResultCount: number, excludeDtsFiles: boolean): NavigateToItem[] {
|
||||
export function getNavigateToItems(sourceFiles: ReadonlyArray<SourceFile>, checker: TypeChecker, cancellationToken: CancellationToken, searchValue: string, maxResultCount: number | undefined, excludeDtsFiles: boolean): NavigateToItem[] {
|
||||
const patternMatcher = createPatternMatcher(searchValue);
|
||||
if (!patternMatcher) return emptyArray;
|
||||
let rawItems: RawNavigateToItem[] = [];
|
||||
@@ -45,7 +45,7 @@ namespace ts.NavigateTo {
|
||||
if (!shouldKeepItem(declaration, checker)) continue;
|
||||
|
||||
if (patternMatcher.patternContainsDots) {
|
||||
const fullMatch = patternMatcher.getFullMatch(getContainers(declaration), name);
|
||||
const fullMatch = patternMatcher.getFullMatch(getContainers(declaration)!, name); // TODO: GH#18217
|
||||
if (fullMatch) {
|
||||
rawItems.push({ name, fileName, matchKind: fullMatch.kind, isCaseSensitive: fullMatch.isCaseSensitive, declaration });
|
||||
}
|
||||
@@ -62,7 +62,7 @@ namespace ts.NavigateTo {
|
||||
case SyntaxKind.ImportClause:
|
||||
case SyntaxKind.ImportSpecifier:
|
||||
case SyntaxKind.ImportEqualsDeclaration:
|
||||
const importer = checker.getSymbolAtLocation((declaration as ImportClause | ImportSpecifier | ImportEqualsDeclaration).name);
|
||||
const importer = checker.getSymbolAtLocation((declaration as ImportClause | ImportSpecifier | ImportEqualsDeclaration).name!)!;
|
||||
const imported = checker.getAliasedSymbol(importer);
|
||||
return importer.escapedName !== imported.escapedName;
|
||||
default:
|
||||
@@ -118,14 +118,14 @@ namespace ts.NavigateTo {
|
||||
}
|
||||
|
||||
// Now, walk up our containers, adding all their names to the container array.
|
||||
declaration = getContainerNode(declaration);
|
||||
let container = getContainerNode(declaration);
|
||||
|
||||
while (declaration) {
|
||||
if (!tryAddSingleDeclarationName(declaration, containers)) {
|
||||
while (container) {
|
||||
if (!tryAddSingleDeclarationName(container, containers)) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
declaration = getContainerNode(declaration);
|
||||
container = getContainerNode(container);
|
||||
}
|
||||
|
||||
return containers;
|
||||
@@ -151,7 +151,7 @@ namespace ts.NavigateTo {
|
||||
textSpan: createTextSpanFromNode(declaration),
|
||||
// TODO(jfreeman): What should be the containerName when the container has a computed name?
|
||||
containerName: containerName ? (<Identifier>containerName).text : "",
|
||||
containerKind: containerName ? getNodeKind(container) : ScriptElementKind.unknown
|
||||
containerKind: containerName ? getNodeKind(container!) : ScriptElementKind.unknown // TODO: GH#18217 Just use `container ? ...`
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,10 +65,10 @@ namespace ts.NavigationBar {
|
||||
}
|
||||
|
||||
function reset() {
|
||||
curSourceFile = undefined;
|
||||
curCancellationToken = undefined;
|
||||
curSourceFile = undefined!;
|
||||
curCancellationToken = undefined!;
|
||||
parentsStack = [];
|
||||
parent = undefined;
|
||||
parent = undefined!;
|
||||
emptyChildItemArray = [];
|
||||
}
|
||||
|
||||
@@ -134,17 +134,17 @@ namespace ts.NavigationBar {
|
||||
mergeChildren(parent.children);
|
||||
sortChildren(parent.children);
|
||||
}
|
||||
parent = parentsStack.pop();
|
||||
parent = parentsStack.pop()!;
|
||||
}
|
||||
|
||||
function addNodeWithRecursiveChild(node: Node, child: Node): void {
|
||||
function addNodeWithRecursiveChild(node: Node, child: Node | undefined): void {
|
||||
startNode(node);
|
||||
addChildrenRecursively(child);
|
||||
endNode();
|
||||
}
|
||||
|
||||
/** Look for navigation bar items in node's subtree, adding them to the current `parent`. */
|
||||
function addChildrenRecursively(node: Node): void {
|
||||
function addChildrenRecursively(node: Node | undefined): void {
|
||||
curCancellationToken.throwIfCancellationRequested();
|
||||
|
||||
if (!node || isToken(node)) {
|
||||
@@ -367,7 +367,8 @@ namespace ts.NavigationBar {
|
||||
// We use 1 NavNode to represent 'A.B.C', but there are multiple source nodes.
|
||||
// Only merge module nodes that have the same chain. Don't merge 'A.B.C' with 'A'!
|
||||
function areSameModule(a: ModuleDeclaration, b: ModuleDeclaration): boolean {
|
||||
return a.body.kind === b.body.kind && (a.body.kind !== SyntaxKind.ModuleDeclaration || areSameModule(<ModuleDeclaration>a.body, <ModuleDeclaration>b.body));
|
||||
// TODO: GH#18217
|
||||
return a.body!.kind === b.body!.kind && (a.body!.kind !== SyntaxKind.ModuleDeclaration || areSameModule(<ModuleDeclaration>a.body, <ModuleDeclaration>b.body));
|
||||
}
|
||||
|
||||
/** Merge source into target. Source should be thrown away after this is called. */
|
||||
@@ -391,7 +392,7 @@ namespace ts.NavigationBar {
|
||||
}
|
||||
|
||||
function compareChildren(child1: NavigationBarNode, child2: NavigationBarNode) {
|
||||
return compareStringsCaseSensitiveUI(tryGetName(child1.node), tryGetName(child2.node))
|
||||
return compareStringsCaseSensitiveUI(tryGetName(child1.node)!, tryGetName(child2.node)!) // TODO: GH#18217
|
||||
|| compareValues(navigationBarNodeKind(child1), navigationBarNodeKind(child2));
|
||||
}
|
||||
|
||||
@@ -407,7 +408,7 @@ namespace ts.NavigationBar {
|
||||
|
||||
const declName = getNameOfDeclaration(<Declaration>node);
|
||||
if (declName) {
|
||||
return unescapeLeadingUnderscores(getPropertyNameForPropertyNameNode(declName));
|
||||
return unescapeLeadingUnderscores(getPropertyNameForPropertyNameNode(declName)!); // TODO: GH#18217
|
||||
}
|
||||
switch (node.kind) {
|
||||
case SyntaxKind.FunctionExpression:
|
||||
@@ -512,7 +513,7 @@ namespace ts.NavigationBar {
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (navigationBarNodeKind(item.parent)) {
|
||||
switch (navigationBarNodeKind(item.parent!)) {
|
||||
case SyntaxKind.ModuleBlock:
|
||||
case SyntaxKind.SourceFile:
|
||||
case SyntaxKind.MethodDeclaration:
|
||||
@@ -522,8 +523,8 @@ namespace ts.NavigationBar {
|
||||
return hasSomeImportantChild(item);
|
||||
}
|
||||
}
|
||||
function hasSomeImportantChild(item: NavigationBarNode) {
|
||||
return forEach(item.children, child => {
|
||||
function hasSomeImportantChild(item: NavigationBarNode): boolean {
|
||||
return some(item.children, child => {
|
||||
const childKind = navigationBarNodeKind(child);
|
||||
return childKind !== SyntaxKind.VariableDeclaration && childKind !== SyntaxKind.BindingElement;
|
||||
});
|
||||
@@ -602,7 +603,7 @@ namespace ts.NavigationBar {
|
||||
* We store 'A' as associated with a NavNode, and use getModuleName to traverse down again.
|
||||
*/
|
||||
function getInteriorModule(decl: ModuleDeclaration): ModuleDeclaration {
|
||||
return decl.body.kind === SyntaxKind.ModuleDeclaration ? getInteriorModule(<ModuleDeclaration>decl.body) : decl;
|
||||
return decl.body!.kind === SyntaxKind.ModuleDeclaration ? getInteriorModule(<ModuleDeclaration>decl.body) : decl; // TODO: GH#18217
|
||||
}
|
||||
|
||||
function isComputedProperty(member: EnumMember): boolean {
|
||||
|
||||
@@ -28,7 +28,7 @@ namespace ts.OrganizeImports {
|
||||
organizeImportsWorker(topLevelExportDecls, coalesceExports);
|
||||
|
||||
for (const ambientModule of sourceFile.statements.filter(isAmbientModule)) {
|
||||
const ambientModuleBody = getModuleBlock(ambientModule as ModuleDeclaration);
|
||||
const ambientModuleBody = getModuleBlock(ambientModule as ModuleDeclaration)!; // TODO: GH#18217
|
||||
|
||||
const ambientModuleImportDecls = ambientModuleBody.statements.filter(isImportDeclaration);
|
||||
organizeImportsWorker(ambientModuleImportDecls, coalesceAndOrganizeImports);
|
||||
@@ -54,10 +54,10 @@ namespace ts.OrganizeImports {
|
||||
// but the consequences of being wrong are very minor.
|
||||
suppressLeadingTrivia(oldImportDecls[0]);
|
||||
|
||||
const oldImportGroups = group(oldImportDecls, importDecl => getExternalModuleName(importDecl.moduleSpecifier));
|
||||
const sortedImportGroups = stableSort(oldImportGroups, (group1, group2) => compareModuleSpecifiers(group1[0].moduleSpecifier, group2[0].moduleSpecifier));
|
||||
const oldImportGroups = group(oldImportDecls, importDecl => getExternalModuleName(importDecl.moduleSpecifier!)!);
|
||||
const sortedImportGroups = stableSort(oldImportGroups, (group1, group2) => compareModuleSpecifiers(group1[0].moduleSpecifier!, group2[0].moduleSpecifier!));
|
||||
const newImportDecls = flatMap(sortedImportGroups, importGroup =>
|
||||
getExternalModuleName(importGroup[0].moduleSpecifier)
|
||||
getExternalModuleName(importGroup[0].moduleSpecifier!)
|
||||
? coalesce(importGroup)
|
||||
: importGroup);
|
||||
|
||||
@@ -86,7 +86,7 @@ namespace ts.OrganizeImports {
|
||||
|
||||
function getModuleBlock(moduleDecl: ModuleDeclaration): ModuleBlock | undefined {
|
||||
const body = moduleDecl.body;
|
||||
return body && !isIdentifier(body) && (isModuleBlock(body) ? body : getModuleBlock(body));
|
||||
return body && !isIdentifier(body) ? (isModuleBlock(body) ? body : getModuleBlock(body)) : undefined;
|
||||
}
|
||||
|
||||
function removeUnusedImports(oldImports: ReadonlyArray<ImportDeclaration>, sourceFile: SourceFile, program: Program) {
|
||||
@@ -172,18 +172,18 @@ namespace ts.OrganizeImports {
|
||||
// Add the namespace import to the existing default ImportDeclaration.
|
||||
const defaultImport = defaultImports[0];
|
||||
coalescedImports.push(
|
||||
updateImportDeclarationAndClause(defaultImport, defaultImport.importClause.name, namespaceImports[0].importClause.namedBindings));
|
||||
updateImportDeclarationAndClause(defaultImport, defaultImport.importClause!.name, namespaceImports[0].importClause!.namedBindings)); // TODO: GH#18217
|
||||
|
||||
return coalescedImports;
|
||||
}
|
||||
|
||||
const sortedNamespaceImports = stableSort(namespaceImports, (i1, i2) =>
|
||||
compareIdentifiers((i1.importClause.namedBindings as NamespaceImport).name, (i2.importClause.namedBindings as NamespaceImport).name));
|
||||
compareIdentifiers((i1.importClause!.namedBindings as NamespaceImport).name, (i2.importClause!.namedBindings as NamespaceImport).name)); // TODO: GH#18217
|
||||
|
||||
for (const namespaceImport of sortedNamespaceImports) {
|
||||
// Drop the name, if any
|
||||
coalescedImports.push(
|
||||
updateImportDeclarationAndClause(namespaceImport, /*name*/ undefined, namespaceImport.importClause.namedBindings));
|
||||
updateImportDeclarationAndClause(namespaceImport, /*name*/ undefined, namespaceImport.importClause!.namedBindings)); // TODO: GH#18217
|
||||
}
|
||||
|
||||
if (defaultImports.length === 0 && namedImports.length === 0) {
|
||||
@@ -193,16 +193,16 @@ namespace ts.OrganizeImports {
|
||||
let newDefaultImport: Identifier | undefined;
|
||||
const newImportSpecifiers: ImportSpecifier[] = [];
|
||||
if (defaultImports.length === 1) {
|
||||
newDefaultImport = defaultImports[0].importClause.name;
|
||||
newDefaultImport = defaultImports[0].importClause!.name;
|
||||
}
|
||||
else {
|
||||
for (const defaultImport of defaultImports) {
|
||||
newImportSpecifiers.push(
|
||||
createImportSpecifier(createIdentifier("default"), defaultImport.importClause.name));
|
||||
createImportSpecifier(createIdentifier("default"), defaultImport.importClause!.name!)); // TODO: GH#18217
|
||||
}
|
||||
}
|
||||
|
||||
newImportSpecifiers.push(...flatMap(namedImports, i => (i.importClause.namedBindings as NamedImports).elements));
|
||||
newImportSpecifiers.push(...flatMap(namedImports, i => (i.importClause!.namedBindings as NamedImports).elements)); // TODO: GH#18217
|
||||
|
||||
const sortedImportSpecifiers = sortSpecifiers(newImportSpecifiers);
|
||||
|
||||
@@ -216,7 +216,7 @@ namespace ts.OrganizeImports {
|
||||
: createNamedImports(emptyArray)
|
||||
: namedImports.length === 0
|
||||
? createNamedImports(sortedImportSpecifiers)
|
||||
: updateNamedImports(namedImports[0].importClause.namedBindings as NamedImports, sortedImportSpecifiers);
|
||||
: updateNamedImports(namedImports[0].importClause!.namedBindings as NamedImports, sortedImportSpecifiers); // TODO: GH#18217
|
||||
|
||||
coalescedImports.push(
|
||||
updateImportDeclarationAndClause(importDecl, newDefaultImport, newNamedImports));
|
||||
@@ -291,7 +291,7 @@ namespace ts.OrganizeImports {
|
||||
}
|
||||
|
||||
const newExportSpecifiers: ExportSpecifier[] = [];
|
||||
newExportSpecifiers.push(...flatMap(namedExports, i => (i.exportClause).elements));
|
||||
newExportSpecifiers.push(...flatMap(namedExports, i => (i.exportClause!).elements));
|
||||
|
||||
const sortedExportSpecifiers = sortSpecifiers(newExportSpecifiers);
|
||||
|
||||
@@ -301,7 +301,7 @@ namespace ts.OrganizeImports {
|
||||
exportDecl,
|
||||
exportDecl.decorators,
|
||||
exportDecl.modifiers,
|
||||
updateNamedExports(exportDecl.exportClause, sortedExportSpecifiers),
|
||||
updateNamedExports(exportDecl.exportClause!, sortedExportSpecifiers),
|
||||
exportDecl.moduleSpecifier));
|
||||
|
||||
return coalescedExports;
|
||||
@@ -342,7 +342,7 @@ namespace ts.OrganizeImports {
|
||||
importDeclaration,
|
||||
importDeclaration.decorators,
|
||||
importDeclaration.modifiers,
|
||||
updateImportClause(importDeclaration.importClause, name, namedBindings),
|
||||
updateImportClause(importDeclaration.importClause!, name, namedBindings), // TODO: GH#18217
|
||||
importDeclaration.moduleSpecifier);
|
||||
}
|
||||
|
||||
@@ -357,8 +357,8 @@ namespace ts.OrganizeImports {
|
||||
const name1 = getExternalModuleName(m1);
|
||||
const name2 = getExternalModuleName(m2);
|
||||
return compareBooleans(name1 === undefined, name2 === undefined) ||
|
||||
compareBooleans(isExternalModuleNameRelative(name1), isExternalModuleNameRelative(name2)) ||
|
||||
compareStringsCaseInsensitive(name1, name2);
|
||||
compareBooleans(isExternalModuleNameRelative(name1!), isExternalModuleNameRelative(name2!)) ||
|
||||
compareStringsCaseInsensitive(name1!, name2!);
|
||||
}
|
||||
|
||||
function compareIdentifiers(s1: Identifier, s2: Identifier) {
|
||||
|
||||
@@ -59,10 +59,10 @@ namespace ts.Completions.PathCompletions {
|
||||
|
||||
// Determine the path to the directory containing the script relative to the root directory it is contained within
|
||||
const relativeDirectory = firstDefined(rootDirs, rootDirectory =>
|
||||
containsPath(rootDirectory, scriptPath, basePath, ignoreCase) ? scriptPath.substr(rootDirectory.length) : undefined);
|
||||
containsPath(rootDirectory, scriptPath, basePath, ignoreCase) ? scriptPath.substr(rootDirectory.length) : undefined)!; // TODO: GH#18217
|
||||
|
||||
// Now find a path for each potential directory that is to be merged with the one containing the script
|
||||
return deduplicate(
|
||||
return deduplicate<string>(
|
||||
rootDirs.map(rootDirectory => combinePaths(rootDirectory, relativeDirectory)),
|
||||
equateStringsCaseSensitive,
|
||||
compareStringsCaseSensitive);
|
||||
@@ -175,9 +175,9 @@ namespace ts.Completions.PathCompletions {
|
||||
const absolute = isRootedDiskPath(baseUrl) ? baseUrl : combinePaths(projectDir, baseUrl);
|
||||
getCompletionEntriesForDirectoryFragment(fragment, normalizePath(absolute), fileExtensions, /*includeExtensions*/ false, host, /*exclude*/ undefined, result);
|
||||
|
||||
for (const path in paths) {
|
||||
const patterns = paths[path];
|
||||
if (paths.hasOwnProperty(path) && patterns) {
|
||||
for (const path in paths!) {
|
||||
const patterns = paths![path];
|
||||
if (paths!.hasOwnProperty(path) && patterns) {
|
||||
for (const { name, kind } of getCompletionsForPathMapping(path, patterns, fragment, baseUrl, fileExtensions, host)) {
|
||||
// Path mappings may provide a duplicate way to get to something we've already added, so don't add again.
|
||||
if (!result.some(entry => entry.name === name)) {
|
||||
@@ -334,7 +334,7 @@ namespace ts.Completions.PathCompletions {
|
||||
}
|
||||
}
|
||||
else if (host.getDirectories) {
|
||||
let typeRoots: ReadonlyArray<string>;
|
||||
let typeRoots: ReadonlyArray<string> | undefined;
|
||||
try {
|
||||
typeRoots = getEffectiveTypeRoots(options, host);
|
||||
}
|
||||
@@ -462,10 +462,10 @@ namespace ts.Completions.PathCompletions {
|
||||
return directoryProbablyExists(path, host);
|
||||
}
|
||||
catch { /*ignore*/ }
|
||||
return undefined;
|
||||
return false;
|
||||
}
|
||||
|
||||
function tryIOAndConsumeErrors<T>(host: LanguageServiceHost, toApply: (...a: any[]) => T, ...args: any[]) {
|
||||
function tryIOAndConsumeErrors<T>(host: LanguageServiceHost, toApply: ((...a: any[]) => T) | undefined, ...args: any[]) {
|
||||
try {
|
||||
return toApply && toApply.apply(host, args);
|
||||
}
|
||||
|
||||
@@ -119,7 +119,7 @@ namespace ts {
|
||||
// First, check that the last part of the dot separated pattern matches the name of the
|
||||
// candidate. If not, then there's no point in proceeding and doing the more
|
||||
// expensive work.
|
||||
const candidateMatch = matchSegment(candidate, lastOrUndefined(dotSeparatedSegments), stringToWordSpans);
|
||||
const candidateMatch = matchSegment(candidate, last(dotSeparatedSegments), stringToWordSpans);
|
||||
if (!candidateMatch) {
|
||||
return undefined;
|
||||
}
|
||||
@@ -203,7 +203,7 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
function matchSegment(candidate: string, segment: Segment, stringToWordSpans: Map<TextSpan[]>): PatternMatch {
|
||||
function matchSegment(candidate: string, segment: Segment, stringToWordSpans: Map<TextSpan[]>): PatternMatch | undefined {
|
||||
// First check if the segment matches as is. This is also useful if the segment contains
|
||||
// characters we would normally strip when splitting into parts that we also may want to
|
||||
// match in the candidate. For example if the segment is "@int" and the candidate is
|
||||
@@ -260,7 +260,7 @@ namespace ts {
|
||||
return bestMatch;
|
||||
}
|
||||
|
||||
function betterMatch(a: PatternMatch | undefined, b: PatternMatch | undefined): PatternMatch {
|
||||
function betterMatch(a: PatternMatch | undefined, b: PatternMatch | undefined): PatternMatch | undefined {
|
||||
return min(a, b, compareMatches);
|
||||
}
|
||||
function compareMatches(a: PatternMatch | undefined, b: PatternMatch | undefined): Comparison {
|
||||
@@ -287,8 +287,8 @@ namespace ts {
|
||||
|
||||
let currentCandidate = 0;
|
||||
let currentChunkSpan = 0;
|
||||
let firstMatch: number;
|
||||
let contiguous: boolean;
|
||||
let firstMatch: number | undefined;
|
||||
let contiguous: boolean | undefined;
|
||||
|
||||
while (true) {
|
||||
// Let's consider our termination cases
|
||||
|
||||
@@ -11,7 +11,7 @@ namespace ts {
|
||||
moduleName: undefined
|
||||
};
|
||||
const importedFiles: FileReference[] = [];
|
||||
let ambientExternalModules: { ref: FileReference, depth: number }[];
|
||||
let ambientExternalModules: { ref: FileReference, depth: number }[] | undefined;
|
||||
let lastToken: SyntaxKind;
|
||||
let currentToken: SyntaxKind;
|
||||
let braceNesting = 0;
|
||||
@@ -336,11 +336,11 @@ namespace ts {
|
||||
importedFiles.push(decl.ref);
|
||||
}
|
||||
}
|
||||
return { referencedFiles: pragmaContext.referencedFiles, typeReferenceDirectives: pragmaContext.typeReferenceDirectives, importedFiles, isLibFile: pragmaContext.hasNoDefaultLib, ambientExternalModules: undefined };
|
||||
return { referencedFiles: pragmaContext.referencedFiles, typeReferenceDirectives: pragmaContext.typeReferenceDirectives, importedFiles, isLibFile: !!pragmaContext.hasNoDefaultLib, ambientExternalModules: undefined };
|
||||
}
|
||||
else {
|
||||
// for global scripts ambient modules still can have augmentations - look for ambient modules with depth > 0
|
||||
let ambientModuleNames: string[];
|
||||
let ambientModuleNames: string[] | undefined;
|
||||
if (ambientExternalModules) {
|
||||
for (const decl of ambientExternalModules) {
|
||||
if (decl.depth === 0) {
|
||||
@@ -354,7 +354,7 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
}
|
||||
return { referencedFiles: pragmaContext.referencedFiles, typeReferenceDirectives: pragmaContext.typeReferenceDirectives, importedFiles, isLibFile: pragmaContext.hasNoDefaultLib, ambientExternalModules: ambientModuleNames };
|
||||
return { referencedFiles: pragmaContext.referencedFiles, typeReferenceDirectives: pragmaContext.typeReferenceDirectives, importedFiles, isLibFile: !!pragmaContext.hasNoDefaultLib, ambientExternalModules: ambientModuleNames };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ namespace ts.refactor.extractSymbol {
|
||||
export function getAvailableActions(context: RefactorContext): ApplicableRefactorInfo[] | undefined {
|
||||
const rangeToExtract = getRangeToExtract(context.file, getRefactorContextSpan(context));
|
||||
|
||||
const targetRange: TargetRange = rangeToExtract.targetRange;
|
||||
const targetRange = rangeToExtract.targetRange;
|
||||
if (targetRange === undefined) {
|
||||
return undefined;
|
||||
}
|
||||
@@ -88,7 +88,7 @@ namespace ts.refactor.extractSymbol {
|
||||
/* Exported for tests */
|
||||
export function getEditsForAction(context: RefactorContext, actionName: string): RefactorEditInfo | undefined {
|
||||
const rangeToExtract = getRangeToExtract(context.file, getRefactorContextSpan(context));
|
||||
const targetRange: TargetRange = rangeToExtract.targetRange;
|
||||
const targetRange = rangeToExtract.targetRange!; // TODO:GH#18217
|
||||
|
||||
const parsedFunctionIndexMatch = /^function_scope_(\d+)$/.exec(actionName);
|
||||
if (parsedFunctionIndexMatch) {
|
||||
@@ -220,7 +220,8 @@ namespace ts.refactor.extractSymbol {
|
||||
return { errors: [createFileDiagnostic(sourceFile, span.start, length, Messages.cannotExtractRange)] };
|
||||
}
|
||||
const statements: Statement[] = [];
|
||||
for (const statement of start.parent.statements) {
|
||||
const start2 = start; // TODO: GH#18217 Need to alias `start` to get this to compile. See https://github.com/Microsoft/TypeScript/issues/19955#issuecomment-344118248
|
||||
for (const statement of (start2.parent as BlockLike).statements) {
|
||||
if (statement === start || statements.length) {
|
||||
const errors = checkNode(statement);
|
||||
if (errors) {
|
||||
@@ -257,13 +258,13 @@ namespace ts.refactor.extractSymbol {
|
||||
if (errors) {
|
||||
return { errors };
|
||||
}
|
||||
return { targetRange: { range: getStatementOrExpressionRange(node), facts: rangeFacts, declarations } };
|
||||
return { targetRange: { range: getStatementOrExpressionRange(node)!, facts: rangeFacts, declarations } }; // TODO: GH#18217
|
||||
|
||||
/**
|
||||
* Attempt to refine the extraction node (generally, by shrinking it) to produce better results.
|
||||
* @param node The unrefined extraction node.
|
||||
*/
|
||||
function refineNode(node: Node) {
|
||||
function refineNode(node: Node): Node {
|
||||
if (isReturnStatement(node)) {
|
||||
if (node.expression) {
|
||||
return node.expression;
|
||||
@@ -279,7 +280,7 @@ namespace ts.refactor.extractSymbol {
|
||||
}
|
||||
}
|
||||
if (numInitializers === 1) {
|
||||
return lastInitializer;
|
||||
return lastInitializer!;
|
||||
}
|
||||
// No special handling if there are multiple initializers.
|
||||
}
|
||||
@@ -309,7 +310,7 @@ namespace ts.refactor.extractSymbol {
|
||||
break;
|
||||
}
|
||||
else if (current.kind === SyntaxKind.Parameter) {
|
||||
const ctorOrMethod = getContainingFunction(current);
|
||||
const ctorOrMethod = getContainingFunction(current)!;
|
||||
if (ctorOrMethod.kind === SyntaxKind.Constructor) {
|
||||
rangeFacts |= RangeFacts.InStaticRegion;
|
||||
}
|
||||
@@ -348,12 +349,12 @@ namespace ts.refactor.extractSymbol {
|
||||
}
|
||||
|
||||
// If we're in a class, see whether we're in a static region (static property initializer, static method, class constructor parameter default)
|
||||
const containingClass: Node = getContainingClass(nodeToCheck);
|
||||
const containingClass = getContainingClass(nodeToCheck);
|
||||
if (containingClass) {
|
||||
checkForStaticContext(nodeToCheck, containingClass);
|
||||
}
|
||||
|
||||
let errors: Diagnostic[];
|
||||
let errors: Diagnostic[] | undefined;
|
||||
let permittedJumps = PermittedJumps.Return;
|
||||
let seenLabels: __String[];
|
||||
|
||||
@@ -370,7 +371,10 @@ namespace ts.refactor.extractSymbol {
|
||||
if (isDeclaration(node)) {
|
||||
const declaringNode = (node.kind === SyntaxKind.VariableDeclaration) ? node.parent.parent : node;
|
||||
if (hasModifier(declaringNode, ModifierFlags.Export)) {
|
||||
(errors || (errors = [])).push(createDiagnosticForNode(node, Messages.cannotExtractExportedEntity));
|
||||
// TODO: GH#18217 Silly to use `errors ||` since it's definitely not defined (see top of `visit`)
|
||||
// Also, if we're only pushing one error, just use `let error: Diagnostic | undefined`!
|
||||
// Also TODO: GH#19956
|
||||
(errors || (errors = [] as Diagnostic[])).push(createDiagnosticForNode(node, Messages.cannotExtractExportedEntity));
|
||||
return true;
|
||||
}
|
||||
declarations.push(node.symbol);
|
||||
@@ -379,16 +383,16 @@ namespace ts.refactor.extractSymbol {
|
||||
// Some things can't be extracted in certain situations
|
||||
switch (node.kind) {
|
||||
case SyntaxKind.ImportDeclaration:
|
||||
(errors || (errors = [])).push(createDiagnosticForNode(node, Messages.cannotExtractImport));
|
||||
(errors || (errors = [] as Diagnostic[])).push(createDiagnosticForNode(node, Messages.cannotExtractImport));
|
||||
return true;
|
||||
case SyntaxKind.SuperKeyword:
|
||||
// For a super *constructor call*, we have to be extracting the entire class,
|
||||
// but a super *method call* simply implies a 'this' reference
|
||||
if (node.parent.kind === SyntaxKind.CallExpression) {
|
||||
// Super constructor call
|
||||
const containingClass = getContainingClass(node);
|
||||
const containingClass = getContainingClass(node)!; // TODO:GH#18217
|
||||
if (containingClass.pos < span.start || containingClass.end >= (span.start + span.length)) {
|
||||
(errors || (errors = [])).push(createDiagnosticForNode(node, Messages.cannotExtractSuper));
|
||||
(errors || (errors = [] as Diagnostic[])).push(createDiagnosticForNode(node, Messages.cannotExtractSuper));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -398,13 +402,13 @@ namespace ts.refactor.extractSymbol {
|
||||
break;
|
||||
}
|
||||
|
||||
if (!node || isFunctionLikeDeclaration(node) || isClassLike(node)) {
|
||||
if (isFunctionLikeDeclaration(node) || isClassLike(node)) {
|
||||
switch (node.kind) {
|
||||
case SyntaxKind.FunctionDeclaration:
|
||||
case SyntaxKind.ClassDeclaration:
|
||||
if (isSourceFile(node.parent) && node.parent.externalModuleIndicator === undefined) {
|
||||
// You cannot extract global declarations
|
||||
(errors || (errors = [])).push(createDiagnosticForNode(node, Messages.functionWillNotBeVisibleInTheNewScope));
|
||||
(errors || (errors = [] as Diagnostic[])).push(createDiagnosticForNode(node, Messages.functionWillNotBeVisibleInTheNewScope));
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -460,13 +464,13 @@ namespace ts.refactor.extractSymbol {
|
||||
if (label) {
|
||||
if (!contains(seenLabels, label.escapedText)) {
|
||||
// attempts to jump to label that is not in range to be extracted
|
||||
(errors || (errors = [])).push(createDiagnosticForNode(node, Messages.cannotExtractRangeContainingLabeledBreakOrContinueStatementWithTargetOutsideOfTheRange));
|
||||
(errors || (errors = [] as Diagnostic[])).push(createDiagnosticForNode(node, Messages.cannotExtractRangeContainingLabeledBreakOrContinueStatementWithTargetOutsideOfTheRange));
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (!(permittedJumps & (node.kind === SyntaxKind.BreakStatement ? PermittedJumps.Break : PermittedJumps.Continue))) {
|
||||
// attempt to break or continue in a forbidden context
|
||||
(errors || (errors = [])).push(createDiagnosticForNode(node, Messages.cannotExtractRangeContainingConditionalBreakOrContinueStatements));
|
||||
(errors || (errors = [] as Diagnostic[])).push(createDiagnosticForNode(node, Messages.cannotExtractRangeContainingConditionalBreakOrContinueStatements));
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -482,7 +486,7 @@ namespace ts.refactor.extractSymbol {
|
||||
rangeFacts |= RangeFacts.HasReturn;
|
||||
}
|
||||
else {
|
||||
(errors || (errors = [])).push(createDiagnosticForNode(node, Messages.cannotExtractRangeContainingConditionalReturnStatement));
|
||||
(errors || (errors = [] as Diagnostic[])).push(createDiagnosticForNode(node, Messages.cannotExtractRangeContainingConditionalReturnStatement));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
@@ -495,7 +499,7 @@ namespace ts.refactor.extractSymbol {
|
||||
}
|
||||
}
|
||||
|
||||
function getStatementOrExpressionRange(node: Node): Statement[] | Expression {
|
||||
function getStatementOrExpressionRange(node: Node): Statement[] | Expression | undefined {
|
||||
if (isStatement(node)) {
|
||||
return [node];
|
||||
}
|
||||
@@ -537,7 +541,7 @@ namespace ts.refactor.extractSymbol {
|
||||
// A function parameter's initializer is actually in the outer scope, not the function declaration
|
||||
if (current.kind === SyntaxKind.Parameter) {
|
||||
// Skip all the way to the outer scope of the function that declared this parameter
|
||||
current = findAncestor(current, parent => isFunctionLikeDeclaration(parent)).parent;
|
||||
current = findAncestor(current, parent => isFunctionLikeDeclaration(parent))!.parent;
|
||||
}
|
||||
|
||||
// We want to find the nearest parent where we can place an "equivalent" sibling to the node we're extracting out of.
|
||||
@@ -557,7 +561,7 @@ namespace ts.refactor.extractSymbol {
|
||||
function getFunctionExtractionAtIndex(targetRange: TargetRange, context: RefactorContext, requestedChangesIndex: number): RefactorEditInfo {
|
||||
const { scopes, readsAndWrites: { target, usagesPerScope, functionErrorsPerScope, exposedVariableDeclarations } } = getPossibleExtractionsWorker(targetRange, context);
|
||||
Debug.assert(!functionErrorsPerScope[requestedChangesIndex].length, "The extraction went missing? How?");
|
||||
context.cancellationToken.throwIfCancellationRequested();
|
||||
context.cancellationToken!.throwIfCancellationRequested(); // TODO: GH#18217
|
||||
return extractFunctionInScope(target, scopes[requestedChangesIndex], usagesPerScope[requestedChangesIndex], exposedVariableDeclarations, targetRange, context);
|
||||
}
|
||||
|
||||
@@ -565,7 +569,7 @@ namespace ts.refactor.extractSymbol {
|
||||
const { scopes, readsAndWrites: { target, usagesPerScope, constantErrorsPerScope, exposedVariableDeclarations } } = getPossibleExtractionsWorker(targetRange, context);
|
||||
Debug.assert(!constantErrorsPerScope[requestedChangesIndex].length, "The extraction went missing? How?");
|
||||
Debug.assert(exposedVariableDeclarations.length === 0, "Extract constant accepted a range containing a variable declaration?");
|
||||
context.cancellationToken.throwIfCancellationRequested();
|
||||
context.cancellationToken!.throwIfCancellationRequested();
|
||||
const expression = isExpression(target)
|
||||
? target
|
||||
: (target.statements[0] as ExpressionStatement).expression;
|
||||
@@ -645,7 +649,7 @@ namespace ts.refactor.extractSymbol {
|
||||
enclosingTextRange,
|
||||
sourceFile,
|
||||
context.program.getTypeChecker(),
|
||||
context.cancellationToken);
|
||||
context.cancellationToken!);
|
||||
return { scopes, readsAndWrites };
|
||||
}
|
||||
|
||||
@@ -679,7 +683,7 @@ namespace ts.refactor.extractSymbol {
|
||||
case SyntaxKind.SetAccessor:
|
||||
return `'set ${scope.name.getText()}'`;
|
||||
default:
|
||||
Debug.assertNever(scope);
|
||||
throw Debug.assertNever(scope);
|
||||
}
|
||||
}
|
||||
function getDescriptionForClassLikeDeclaration(scope: ClassLikeDeclaration): string {
|
||||
@@ -719,12 +723,12 @@ namespace ts.refactor.extractSymbol {
|
||||
|
||||
const functionName = createIdentifier(functionNameText);
|
||||
|
||||
let returnType: TypeNode;
|
||||
let returnType: TypeNode | undefined;
|
||||
const parameters: ParameterDeclaration[] = [];
|
||||
const callArguments: Identifier[] = [];
|
||||
let writes: UsageEntry[];
|
||||
let writes: UsageEntry[] | undefined;
|
||||
usagesInScope.forEach((usage, name) => {
|
||||
let typeNode: TypeNode;
|
||||
let typeNode: TypeNode | undefined;
|
||||
if (!isJS) {
|
||||
let type = checker.getTypeOfSymbolAtLocation(usage.symbol, usage.node);
|
||||
// Widen the type so we don't emit nonsense annotations like "function fn(x: 3) {"
|
||||
@@ -764,7 +768,7 @@ namespace ts.refactor.extractSymbol {
|
||||
// to avoid problems when there are literal types present
|
||||
if (isExpression(node) && !isJS) {
|
||||
const contextualType = checker.getContextualType(node);
|
||||
returnType = checker.typeToTypeNode(contextualType, scope, NodeBuilderFlags.NoTruncation);
|
||||
returnType = checker.typeToTypeNode(contextualType!, scope, NodeBuilderFlags.NoTruncation); // TODO: GH#18217
|
||||
}
|
||||
|
||||
const { body, returnValueProperty } = transformFunctionBody(node, exposedVariableDeclarations, writes, substitutions, !!(range.facts & RangeFacts.HasReturn));
|
||||
@@ -861,8 +865,8 @@ namespace ts.refactor.extractSymbol {
|
||||
/*name*/ getSynthesizedDeepClone(variableDeclaration.name)));
|
||||
|
||||
// Being returned through an object literal will have widened the type.
|
||||
const variableType: TypeNode = checker.typeToTypeNode(
|
||||
checker.getBaseTypeOfLiteralType(checker.getTypeAtLocation(variableDeclaration)),
|
||||
const variableType: TypeNode | undefined = checker.typeToTypeNode(
|
||||
checker.getBaseTypeOfLiteralType(checker.getTypeAtLocation(variableDeclaration)!), // TODO: GH#18217
|
||||
scope,
|
||||
NodeBuilderFlags.NoTruncation);
|
||||
|
||||
@@ -1006,7 +1010,7 @@ namespace ts.refactor.extractSymbol {
|
||||
|
||||
const variableType = isJS || !checker.isContextSensitive(node)
|
||||
? undefined
|
||||
: checker.typeToTypeNode(checker.getContextualType(node), scope, NodeBuilderFlags.NoTruncation);
|
||||
: checker.typeToTypeNode(checker.getContextualType(node)!, scope, NodeBuilderFlags.NoTruncation); // TODO: GH#18217
|
||||
|
||||
const initializer = transformConstantInitializer(node, substitutions);
|
||||
suppressLeadingAndTrailingTrivia(initializer);
|
||||
@@ -1032,7 +1036,7 @@ namespace ts.refactor.extractSymbol {
|
||||
|
||||
const localReference = createPropertyAccess(
|
||||
rangeFacts & RangeFacts.InStaticRegion
|
||||
? createIdentifier(scope.name.getText())
|
||||
? createIdentifier(scope.name!.getText()) // TODO: GH#18217
|
||||
: createThis(),
|
||||
createIdentifier(localNameText));
|
||||
|
||||
@@ -1147,7 +1151,7 @@ namespace ts.refactor.extractSymbol {
|
||||
function getCalledExpression(scope: Node, range: TargetRange, functionNameText: string): Expression {
|
||||
const functionReference = createIdentifier(functionNameText);
|
||||
if (isClassLike(scope)) {
|
||||
const lhs = range.facts & RangeFacts.InStaticRegion ? createIdentifier(scope.name.text) : createThis();
|
||||
const lhs = range.facts & RangeFacts.InStaticRegion ? createIdentifier(scope.name!.text) : createThis(); // TODO: GH#18217
|
||||
return createPropertyAccess(lhs, functionReference);
|
||||
}
|
||||
else {
|
||||
@@ -1155,13 +1159,13 @@ namespace ts.refactor.extractSymbol {
|
||||
}
|
||||
}
|
||||
|
||||
function transformFunctionBody(body: Node, exposedVariableDeclarations: ReadonlyArray<VariableDeclaration>, writes: ReadonlyArray<UsageEntry>, substitutions: ReadonlyMap<Node>, hasReturn: boolean): { body: Block, returnValueProperty: string } {
|
||||
function transformFunctionBody(body: Node, exposedVariableDeclarations: ReadonlyArray<VariableDeclaration>, writes: ReadonlyArray<UsageEntry> | undefined, substitutions: ReadonlyMap<Node>, hasReturn: boolean): { body: Block, returnValueProperty: string | undefined } {
|
||||
const hasWritesOrVariableDeclarations = writes !== undefined || exposedVariableDeclarations.length > 0;
|
||||
if (isBlock(body) && !hasWritesOrVariableDeclarations && substitutions.size === 0) {
|
||||
// already block, no declarations or writes to propagate back, no substitutions - can use node as is
|
||||
return { body: createBlock(body.statements, /*multLine*/ true), returnValueProperty: undefined };
|
||||
}
|
||||
let returnValueProperty: string;
|
||||
let returnValueProperty: string | undefined;
|
||||
let ignoreReturns = false;
|
||||
const statements = createNodeArray(isBlock(body) ? body.statements.slice(0) : [isStatement(body) ? body : createReturn(<Expression>body)]);
|
||||
// rewrite body if either there are writes that should be propagated back via return statements or there are substitutions
|
||||
@@ -1191,7 +1195,7 @@ namespace ts.refactor.extractSymbol {
|
||||
if (!returnValueProperty) {
|
||||
returnValueProperty = "__return";
|
||||
}
|
||||
assignments.unshift(createPropertyAssignment(returnValueProperty, visitNode((<ReturnStatement>node).expression, visitor)));
|
||||
assignments.unshift(createPropertyAssignment(returnValueProperty, visitNode((<ReturnStatement>node).expression!, visitor)));
|
||||
}
|
||||
if (assignments.length === 1) {
|
||||
return createReturn(assignments[0].name as Expression);
|
||||
@@ -1224,7 +1228,7 @@ namespace ts.refactor.extractSymbol {
|
||||
|
||||
function getStatementsOrClassElements(scope: Scope): ReadonlyArray<Statement> | ReadonlyArray<ClassElement> {
|
||||
if (isFunctionLikeDeclaration(scope)) {
|
||||
const body = scope.body;
|
||||
const body = scope.body!; // TODO: GH#18217
|
||||
if (isBlock(body)) {
|
||||
return body.statements;
|
||||
}
|
||||
@@ -1273,7 +1277,7 @@ namespace ts.refactor.extractSymbol {
|
||||
prevMember = member;
|
||||
}
|
||||
|
||||
Debug.assert(prevMember !== undefined); // If the loop didn't return, then it did set prevMember.
|
||||
if (prevMember === undefined) return Debug.fail(); // If the loop didn't return, then it did set prevMember.
|
||||
return prevMember;
|
||||
}
|
||||
|
||||
@@ -1289,7 +1293,7 @@ namespace ts.refactor.extractSymbol {
|
||||
|
||||
for (let curr = (prevScope || node).parent; ; curr = curr.parent) {
|
||||
if (isBlockLike(curr)) {
|
||||
let prevStatement;
|
||||
let prevStatement: Statement | undefined;
|
||||
for (const statement of curr.statements) {
|
||||
if (statement.pos > node.pos) {
|
||||
break;
|
||||
@@ -1304,26 +1308,23 @@ namespace ts.refactor.extractSymbol {
|
||||
}
|
||||
|
||||
// There must be at least one statement since we started in one.
|
||||
Debug.assert(prevStatement !== undefined);
|
||||
return prevStatement;
|
||||
return Debug.assertDefined(prevStatement);
|
||||
}
|
||||
|
||||
if (curr === scope) {
|
||||
Debug.fail("Didn't encounter a block-like before encountering scope");
|
||||
break;
|
||||
}
|
||||
Debug.assert(curr !== scope, "Didn't encounter a block-like before encountering scope");
|
||||
}
|
||||
}
|
||||
|
||||
function getPropertyAssignmentsForWritesAndVariableDeclarations(
|
||||
exposedVariableDeclarations: ReadonlyArray<VariableDeclaration>,
|
||||
writes: ReadonlyArray<UsageEntry>) {
|
||||
|
||||
writes: ReadonlyArray<UsageEntry> | undefined
|
||||
): ShorthandPropertyAssignment[] {
|
||||
const variableAssignments = map(exposedVariableDeclarations, v => createShorthandPropertyAssignment(v.symbol.name));
|
||||
const writeAssignments = map(writes, w => createShorthandPropertyAssignment(w.symbol.name));
|
||||
|
||||
// TODO: GH#18217 `variableAssignments` not possibly undefined!
|
||||
return variableAssignments === undefined
|
||||
? writeAssignments
|
||||
? writeAssignments!
|
||||
: writeAssignments === undefined
|
||||
? variableAssignments
|
||||
: variableAssignments.concat(writeAssignments);
|
||||
@@ -1405,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)) {
|
||||
else if (checker.getTypeAtLocation(expression)!.flags & (TypeFlags.Void | TypeFlags.Never)) { // TODO: GH#18217
|
||||
expressionDiagnostic = createDiagnosticForNode(expression, Messages.uselessConstantType);
|
||||
}
|
||||
|
||||
@@ -1445,7 +1446,7 @@ namespace ts.refactor.extractSymbol {
|
||||
// will use the contextual type of an expression as the return type of the extracted
|
||||
// method (and will therefore "use" all the types involved).
|
||||
if (inGenericContext && !isReadonlyArray(targetRange.range)) {
|
||||
const contextualType = checker.getContextualType(targetRange.range);
|
||||
const contextualType = checker.getContextualType(targetRange.range)!; // TODO: GH#18217
|
||||
recordTypeParameterUsages(contextualType);
|
||||
}
|
||||
|
||||
@@ -1554,7 +1555,7 @@ namespace ts.refactor.extractSymbol {
|
||||
|
||||
function collectUsages(node: Node, valueUsage = Usage.Read) {
|
||||
if (inGenericContext) {
|
||||
const type = checker.getTypeAtLocation(node);
|
||||
const type = checker.getTypeAtLocation(node)!; // TODO: GH#18217
|
||||
recordTypeParameterUsages(type);
|
||||
}
|
||||
|
||||
@@ -1697,7 +1698,7 @@ namespace ts.refactor.extractSymbol {
|
||||
const decl = find(visibleDeclarationsInExtractedRange, d => d.symbol === sym);
|
||||
if (decl) {
|
||||
if (isVariableDeclaration(decl)) {
|
||||
const idString = decl.symbol.id.toString();
|
||||
const idString = decl.symbol.id!.toString();
|
||||
if (!exposedVariableSymbolSet.has(idString)) {
|
||||
exposedVariableDeclarations.push(decl);
|
||||
exposedVariableSymbolSet.set(idString, true);
|
||||
@@ -1725,7 +1726,7 @@ namespace ts.refactor.extractSymbol {
|
||||
: checker.getSymbolAtLocation(identifier);
|
||||
}
|
||||
|
||||
function tryReplaceWithQualifiedNameOrPropertyAccess(symbol: Symbol, scopeDecl: Node, isTypeNode: boolean): PropertyAccessExpression | EntityName {
|
||||
function tryReplaceWithQualifiedNameOrPropertyAccess(symbol: Symbol | undefined, scopeDecl: Node, isTypeNode: boolean): PropertyAccessExpression | EntityName | undefined {
|
||||
if (!symbol) {
|
||||
return undefined;
|
||||
}
|
||||
@@ -1743,7 +1744,7 @@ namespace ts.refactor.extractSymbol {
|
||||
}
|
||||
}
|
||||
|
||||
function getParentNodeInSpan(node: Node, file: SourceFile, span: TextSpan): Node {
|
||||
function getParentNodeInSpan(node: Node | undefined, file: SourceFile, span: TextSpan): Node | undefined {
|
||||
if (!node) return undefined;
|
||||
|
||||
while (node.parent) {
|
||||
@@ -1768,15 +1769,16 @@ namespace ts.refactor.extractSymbol {
|
||||
* in the sense of something that you could extract on
|
||||
*/
|
||||
function isExtractableExpression(node: Node): boolean {
|
||||
switch (node.parent.kind) {
|
||||
const { parent } = node;
|
||||
switch (parent.kind) {
|
||||
case SyntaxKind.EnumMember:
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (node.kind) {
|
||||
case SyntaxKind.StringLiteral:
|
||||
return node.parent.kind !== SyntaxKind.ImportDeclaration &&
|
||||
node.parent.kind !== SyntaxKind.ImportSpecifier;
|
||||
return parent.kind !== SyntaxKind.ImportDeclaration &&
|
||||
parent.kind !== SyntaxKind.ImportSpecifier;
|
||||
|
||||
case SyntaxKind.SpreadElement:
|
||||
case SyntaxKind.ObjectBindingPattern:
|
||||
@@ -1784,9 +1786,9 @@ namespace ts.refactor.extractSymbol {
|
||||
return false;
|
||||
|
||||
case SyntaxKind.Identifier:
|
||||
return node.parent.kind !== SyntaxKind.BindingElement &&
|
||||
node.parent.kind !== SyntaxKind.ImportSpecifier &&
|
||||
node.parent.kind !== SyntaxKind.ExportSpecifier;
|
||||
return parent.kind !== SyntaxKind.BindingElement &&
|
||||
parent.kind !== SyntaxKind.ImportSpecifier &&
|
||||
parent.kind !== SyntaxKind.ExportSpecifier;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -101,11 +101,11 @@ namespace ts.refactor.generateGetAccessorAndSetAccessor {
|
||||
}
|
||||
|
||||
function createAccessorAccessExpression (fieldName: AcceptedNameType, isStatic: boolean, container: ContainerDeclaration) {
|
||||
const leftHead = isStatic ? (<ClassLikeDeclaration>container).name : createThis();
|
||||
const leftHead = isStatic ? (<ClassLikeDeclaration>container).name! : createThis(); // TODO: GH#18217
|
||||
return isIdentifier(fieldName) ? createPropertyAccess(leftHead, fieldName) : createElementAccess(leftHead, createLiteral(fieldName));
|
||||
}
|
||||
|
||||
function getModifiers(isJS: boolean, isStatic: boolean, accessModifier: SyntaxKind.PublicKeyword | SyntaxKind.PrivateKeyword): NodeArray<Modifier> {
|
||||
function getModifiers(isJS: boolean, isStatic: boolean, accessModifier: SyntaxKind.PublicKeyword | SyntaxKind.PrivateKeyword): NodeArray<Modifier> | undefined {
|
||||
const modifiers = append<Modifier>(
|
||||
!isJS ? [createToken(accessModifier) as Token<SyntaxKind.PublicKeyword> | Token<SyntaxKind.PrivateKeyword>] : undefined,
|
||||
isStatic ? createToken(SyntaxKind.StaticKeyword) : undefined
|
||||
@@ -124,7 +124,7 @@ namespace ts.refactor.generateGetAccessorAndSetAccessor {
|
||||
const declaration = findAncestor(node.parent, isAcceptedDeclaration);
|
||||
// make sure declaration have AccessibilityModifier or Static Modifier or Readonly Modifier
|
||||
const meaning = ModifierFlags.AccessibilityModifier | ModifierFlags.Static | ModifierFlags.Readonly;
|
||||
if (!declaration || !rangeOverlapsWithStartEnd(declaration.name, startPosition, endPosition)
|
||||
if (!declaration || !rangeOverlapsWithStartEnd(declaration.name, startPosition, endPosition!) // TODO: GH#18217
|
||||
|| !isConvertableName(declaration.name) || (getModifierFlags(declaration) | meaning) !== meaning) return undefined;
|
||||
|
||||
const name = declaration.name.text;
|
||||
@@ -144,12 +144,12 @@ namespace ts.refactor.generateGetAccessorAndSetAccessor {
|
||||
};
|
||||
}
|
||||
|
||||
function generateGetAccessor(fieldName: AcceptedNameType, accessorName: AcceptedNameType, type: TypeNode, modifiers: ModifiersArray | undefined, isStatic: boolean, container: ContainerDeclaration) {
|
||||
function generateGetAccessor(fieldName: AcceptedNameType, accessorName: AcceptedNameType, type: TypeNode | undefined, modifiers: ModifiersArray | undefined, isStatic: boolean, container: ContainerDeclaration) {
|
||||
return createGetAccessor(
|
||||
/*decorators*/ undefined,
|
||||
modifiers,
|
||||
accessorName,
|
||||
/*parameters*/ undefined,
|
||||
/*parameters*/ undefined!, // TODO: GH#18217
|
||||
type,
|
||||
createBlock([
|
||||
createReturn(
|
||||
@@ -159,7 +159,7 @@ namespace ts.refactor.generateGetAccessorAndSetAccessor {
|
||||
);
|
||||
}
|
||||
|
||||
function generateSetAccessor(fieldName: AcceptedNameType, accessorName: AcceptedNameType, type: TypeNode, modifiers: ModifiersArray | undefined, isStatic: boolean, container: ContainerDeclaration) {
|
||||
function generateSetAccessor(fieldName: AcceptedNameType, accessorName: AcceptedNameType, type: TypeNode | undefined, modifiers: ModifiersArray | undefined, isStatic: boolean, container: ContainerDeclaration) {
|
||||
return createSetAccessor(
|
||||
/*decorators*/ undefined,
|
||||
modifiers,
|
||||
@@ -226,9 +226,8 @@ namespace ts.refactor.generateGetAccessorAndSetAccessor {
|
||||
if (!constructor.body) return;
|
||||
const { file, program, cancellationToken } = context;
|
||||
|
||||
const referenceEntries = mapDefined(FindAllReferences.getReferenceEntriesForNode(originalName.parent.pos, originalName, program, [file], cancellationToken), entry => (
|
||||
(entry.type === "node" && rangeContainsRange(constructor, entry.node) && isIdentifier(entry.node) && isWriteAccess(entry.node)) ? entry.node : undefined
|
||||
));
|
||||
const referenceEntries = mapDefined(FindAllReferences.getReferenceEntriesForNode(originalName.parent.pos, originalName, program, [file], cancellationToken!), entry => // TODO: GH#18217
|
||||
(entry.type === "node" && rangeContainsRange(constructor, entry.node) && isIdentifier(entry.node) && isWriteAccess(entry.node)) ? entry.node : undefined);
|
||||
|
||||
forEach(referenceEntries, entry => {
|
||||
const parent = entry.parent;
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
namespace ts.refactor {
|
||||
const refactorName = "Move to a new file";
|
||||
registerRefactor(refactorName, {
|
||||
getAvailableActions(context): ApplicableRefactorInfo[] {
|
||||
getAvailableActions(context): ApplicableRefactorInfo[] | undefined {
|
||||
if (!context.preferences.allowTextChangesInNewFiles || getFirstAndLastStatementToMove(context) === undefined) return undefined;
|
||||
const description = getLocaleSpecificMessage(Diagnostics.Move_to_a_new_file);
|
||||
return [{ name: refactorName, description, actions: [{ name: refactorName, description }] }];
|
||||
@@ -82,7 +82,7 @@ namespace ts.refactor {
|
||||
case SyntaxKind.ImportEqualsDeclaration:
|
||||
return !hasModifier(node, ModifierFlags.Export);
|
||||
case SyntaxKind.VariableStatement:
|
||||
return (node as VariableStatement).declarationList.declarations.every(d => d.initializer && isRequireCall(d.initializer, /*checkArgumentIsStringLiteralLike*/ true));
|
||||
return (node as VariableStatement).declarationList.declarations.every(d => !!d.initializer && isRequireCall(d.initializer, /*checkArgumentIsStringLiteralLike*/ true));
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
@@ -139,7 +139,7 @@ namespace ts.refactor {
|
||||
function deleteUnusedOldImports(oldFile: SourceFile, toMove: ReadonlyArray<Statement>, changes: textChanges.ChangeTracker, toDelete: ReadonlySymbolSet, checker: TypeChecker) {
|
||||
for (const statement of oldFile.statements) {
|
||||
if (contains(toMove, statement)) continue;
|
||||
forEachImportInStatement(statement, i => deleteUnusedImports(oldFile, i, changes, name => toDelete.has(checker.getSymbolAtLocation(name))));
|
||||
forEachImportInStatement(statement, i => deleteUnusedImports(oldFile, i, changes, name => toDelete.has(checker.getSymbolAtLocation(name)!)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -152,7 +152,7 @@ namespace ts.refactor {
|
||||
const shouldMove = (name: Identifier): boolean => {
|
||||
const symbol = isBindingElement(name.parent)
|
||||
? getPropertySymbolFromBindingElement(checker, name.parent as BindingElement & { name: Identifier })
|
||||
: skipAlias(checker.getSymbolAtLocation(name), checker);
|
||||
: skipAlias(checker.getSymbolAtLocation(name)!, checker); // TODO: GH#18217
|
||||
return !!symbol && movedSymbols.has(symbol);
|
||||
};
|
||||
deleteUnusedImports(sourceFile, importNode, changes, shouldMove); // These will be changed to imports from the new file
|
||||
@@ -202,7 +202,7 @@ namespace ts.refactor {
|
||||
const imports: string[] = [];
|
||||
newFileNeedExport.forEach(symbol => {
|
||||
if (symbol.escapedName === InternalSymbolName.Default) {
|
||||
defaultImport = createIdentifier(symbolNameNoDefault(symbol));
|
||||
defaultImport = createIdentifier(symbolNameNoDefault(symbol)!); // TODO: GH#18217
|
||||
}
|
||||
else {
|
||||
imports.push(symbol.name);
|
||||
@@ -325,7 +325,7 @@ namespace ts.refactor {
|
||||
const copiedOldImports: SupportedImportStatement[] = [];
|
||||
for (const oldStatement of oldFile.statements) {
|
||||
forEachImportInStatement(oldStatement, i => {
|
||||
append(copiedOldImports, filterImport(i, moduleSpecifierFromImport(i), name => importsToCopy.has(checker.getSymbolAtLocation(name))));
|
||||
append(copiedOldImports, filterImport(i, moduleSpecifierFromImport(i), name => importsToCopy.has(checker.getSymbolAtLocation(name)!)));
|
||||
});
|
||||
}
|
||||
|
||||
@@ -360,7 +360,7 @@ namespace ts.refactor {
|
||||
let newModuleName = moduleName;
|
||||
for (let i = 1; ; i++) {
|
||||
const name = combinePaths(inDirectory, newModuleName + extension);
|
||||
if (!host.fileExists(name)) return newModuleName;
|
||||
if (!host.fileExists!(name)) return newModuleName; // TODO: GH#18217
|
||||
newModuleName = `${moduleName}.${i}`;
|
||||
}
|
||||
}
|
||||
@@ -564,7 +564,7 @@ namespace ts.refactor {
|
||||
}
|
||||
}
|
||||
|
||||
function forEachTopLevelDeclaration<T>(statement: Statement, cb: (node: TopLevelDeclaration) => T): T {
|
||||
function forEachTopLevelDeclaration<T>(statement: Statement, cb: (node: TopLevelDeclaration) => T): T | undefined {
|
||||
switch (statement.kind) {
|
||||
case SyntaxKind.FunctionDeclaration:
|
||||
case SyntaxKind.ClassDeclaration:
|
||||
@@ -611,7 +611,7 @@ namespace ts.refactor {
|
||||
return !isExpressionStatement(decl) && hasModifier(decl, ModifierFlags.Export);
|
||||
}
|
||||
else {
|
||||
return getNamesToExportInCommonJS(decl).some(name => sourceFile.symbol.exports.has(escapeLeadingUnderscores(name)));
|
||||
return getNamesToExportInCommonJS(decl).some(name => sourceFile.symbol.exports!.has(escapeLeadingUnderscores(name)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -650,7 +650,7 @@ namespace ts.refactor {
|
||||
switch (decl.kind) {
|
||||
case SyntaxKind.FunctionDeclaration:
|
||||
case SyntaxKind.ClassDeclaration:
|
||||
return [decl.name.text];
|
||||
return [decl.name!.text]; // TODO: GH#18217
|
||||
case SyntaxKind.VariableStatement:
|
||||
return mapDefined(decl.declarationList.declarations, d => isIdentifier(d.name) ? d.name.text : undefined);
|
||||
case SyntaxKind.ModuleDeclaration:
|
||||
@@ -658,11 +658,11 @@ namespace ts.refactor {
|
||||
case SyntaxKind.TypeAliasDeclaration:
|
||||
case SyntaxKind.InterfaceDeclaration:
|
||||
case SyntaxKind.ImportEqualsDeclaration:
|
||||
return undefined;
|
||||
return emptyArray;
|
||||
case SyntaxKind.ExpressionStatement:
|
||||
return Debug.fail(); // Shouldn't try to add 'export' keyword to `exports.x = ...`
|
||||
default:
|
||||
Debug.assertNever(decl);
|
||||
return Debug.assertNever(decl);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ namespace ts.Rename {
|
||||
}
|
||||
|
||||
// Cannot rename `default` as in `import { default as foo } from "./someModule";
|
||||
if (isIdentifier(node) && node.originalKeywordKind === SyntaxKind.DefaultKeyword && symbol.parent.flags & SymbolFlags.Module) {
|
||||
if (isIdentifier(node) && node.originalKeywordKind === SyntaxKind.DefaultKeyword && symbol.parent!.flags & SymbolFlags.Module) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
@@ -69,14 +69,15 @@ namespace ts.Rename {
|
||||
}
|
||||
|
||||
function getRenameInfoError(diagnostic: DiagnosticMessage): RenameInfo {
|
||||
// TODO: GH#18217
|
||||
return {
|
||||
canRename: false,
|
||||
localizedErrorMessage: getLocaleSpecificMessage(diagnostic),
|
||||
displayName: undefined,
|
||||
fullDisplayName: undefined,
|
||||
kind: undefined,
|
||||
kindModifiers: undefined,
|
||||
triggerSpan: undefined
|
||||
displayName: undefined!,
|
||||
fullDisplayName: undefined!,
|
||||
kind: undefined!,
|
||||
kindModifiers: undefined!,
|
||||
triggerSpan: undefined!
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
+96
-89
@@ -2,7 +2,7 @@ namespace ts {
|
||||
/** The version of the language service API */
|
||||
export const servicesVersion = "0.8";
|
||||
|
||||
function createNode<TKind extends SyntaxKind>(kind: TKind, pos: number, end: number, parent?: Node): NodeObject | TokenObject<TKind> | IdentifierObject {
|
||||
function createNode<TKind extends SyntaxKind>(kind: TKind, pos: number, end: number, parent: Node): NodeObject | TokenObject<TKind> | IdentifierObject {
|
||||
const node = isNodeKind(kind) ? new NodeObject(kind, pos, end) :
|
||||
kind === SyntaxKind.Identifier ? new IdentifierObject(SyntaxKind.Identifier, pos, end) :
|
||||
new TokenObject(kind, pos, end);
|
||||
@@ -17,6 +17,7 @@ namespace ts {
|
||||
public end: number;
|
||||
public flags: NodeFlags;
|
||||
public parent: Node;
|
||||
public symbol: Symbol;
|
||||
public jsDoc: JSDoc[];
|
||||
public original: Node;
|
||||
public transformFlags: TransformFlags;
|
||||
@@ -26,8 +27,8 @@ namespace ts {
|
||||
this.pos = pos;
|
||||
this.end = end;
|
||||
this.flags = NodeFlags.None;
|
||||
this.transformFlags = undefined;
|
||||
this.parent = undefined;
|
||||
this.transformFlags = undefined!; // TODO: GH#18217
|
||||
this.parent = undefined!;
|
||||
this.kind = kind;
|
||||
}
|
||||
|
||||
@@ -96,20 +97,20 @@ namespace ts {
|
||||
return this._children || (this._children = createChildren(this, sourceFile));
|
||||
}
|
||||
|
||||
public getFirstToken(sourceFile?: SourceFile): Node {
|
||||
public getFirstToken(sourceFile?: SourceFile): Node | undefined {
|
||||
this.assertHasRealPosition();
|
||||
const children = this.getChildren(sourceFile);
|
||||
if (!children.length) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const child = find(children, kid => kid.kind < SyntaxKind.FirstJSDocNode || kid.kind > SyntaxKind.LastJSDocNode);
|
||||
const child = find(children, kid => kid.kind < SyntaxKind.FirstJSDocNode || kid.kind > SyntaxKind.LastJSDocNode)!;
|
||||
return child.kind < SyntaxKind.FirstNode ?
|
||||
child :
|
||||
child.getFirstToken(sourceFile);
|
||||
}
|
||||
|
||||
public getLastToken(sourceFile?: SourceFile): Node {
|
||||
public getLastToken(sourceFile?: SourceFile): Node | undefined {
|
||||
this.assertHasRealPosition();
|
||||
const children = this.getChildren(sourceFile);
|
||||
|
||||
@@ -121,7 +122,7 @@ namespace ts {
|
||||
return child.kind < SyntaxKind.FirstNode ? child : child.getLastToken(sourceFile);
|
||||
}
|
||||
|
||||
public forEachChild<T>(cbNode: (node: Node) => T, cbNodeArray?: (nodes: NodeArray<Node>) => T): T {
|
||||
public forEachChild<T>(cbNode: (node: Node) => T, cbNodeArray?: (nodes: NodeArray<Node>) => T): T | undefined {
|
||||
return forEachChild(this, cbNode, cbNodeArray);
|
||||
}
|
||||
}
|
||||
@@ -200,14 +201,16 @@ namespace ts {
|
||||
public end: number;
|
||||
public flags: NodeFlags;
|
||||
public parent: Node;
|
||||
public symbol: Symbol;
|
||||
public jsDocComments: JSDoc[];
|
||||
public transformFlags: TransformFlags;
|
||||
|
||||
constructor(pos: number, end: number) {
|
||||
// Set properties in same order as NodeObject
|
||||
this.pos = pos;
|
||||
this.end = end;
|
||||
this.flags = NodeFlags.None;
|
||||
this.parent = undefined;
|
||||
this.parent = undefined!;
|
||||
}
|
||||
|
||||
public getSourceFile(): SourceFile {
|
||||
@@ -254,22 +257,22 @@ namespace ts {
|
||||
}
|
||||
|
||||
public getChildAt(): Node {
|
||||
return undefined;
|
||||
return undefined!; // TODO: GH#18217
|
||||
}
|
||||
|
||||
public getChildren(): Node[] {
|
||||
return emptyArray;
|
||||
}
|
||||
|
||||
public getFirstToken(): Node {
|
||||
public getFirstToken(): Node | undefined {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
public getLastToken(): Node {
|
||||
public getLastToken(): Node | undefined {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
public forEachChild<T>(): T {
|
||||
public forEachChild<T>(): T | undefined {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
@@ -277,7 +280,8 @@ namespace ts {
|
||||
class SymbolObject implements Symbol {
|
||||
flags: SymbolFlags;
|
||||
escapedName: __String;
|
||||
declarations?: Declaration[];
|
||||
declarations: Declaration[];
|
||||
valueDeclaration: Declaration;
|
||||
|
||||
// Undefined is used to indicate the value has not been computed. If, after computing, the
|
||||
// symbol has no doc comment, then the empty array will be returned.
|
||||
@@ -330,6 +334,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
class TokenObject<TKind extends SyntaxKind> extends TokenOrIdentifierObject implements Token<TKind> {
|
||||
public symbol: Symbol;
|
||||
public kind: TKind;
|
||||
|
||||
constructor(kind: TKind, pos: number, end: number) {
|
||||
@@ -341,6 +346,8 @@ namespace ts {
|
||||
class IdentifierObject extends TokenOrIdentifierObject implements Identifier {
|
||||
public kind: SyntaxKind.Identifier;
|
||||
public escapedText: __String;
|
||||
public symbol: Symbol;
|
||||
public autoGenerateFlags: GeneratedIdentifierFlags;
|
||||
_primaryExpressionBrand: any;
|
||||
_memberExpressionBrand: any;
|
||||
_leftHandSideExpressionBrand: any;
|
||||
@@ -364,7 +371,7 @@ namespace ts {
|
||||
flags: TypeFlags;
|
||||
objectFlags?: ObjectFlags;
|
||||
id: number;
|
||||
symbol?: Symbol;
|
||||
symbol: Symbol;
|
||||
constructor(checker: TypeChecker, flags: TypeFlags) {
|
||||
this.checker = checker;
|
||||
this.flags = flags;
|
||||
@@ -503,7 +510,7 @@ namespace ts {
|
||||
let doc = JsDoc.getJsDocCommentsFromDeclarations(declarations);
|
||||
if (doc.length === 0 || declarations.some(hasJSDocInheritDocTag)) {
|
||||
for (const declaration of declarations) {
|
||||
const inheritedDocs = findInheritedJSDocComments(declaration, declaration.symbol.name, checker);
|
||||
const inheritedDocs = findInheritedJSDocComments(declaration, declaration.symbol.name, checker!); // TODO: GH#18217
|
||||
// TODO: GH#16312 Return a ReadonlyArray, avoid copying inheritedDocs
|
||||
if (inheritedDocs) doc = doc.length === 0 ? inheritedDocs.slice() : inheritedDocs.concat(lineBreakPart(), doc);
|
||||
}
|
||||
@@ -600,7 +607,7 @@ namespace ts {
|
||||
const { line } = this.getLineAndCharacterOfPosition(pos);
|
||||
const lineStarts = this.getLineStarts();
|
||||
|
||||
let lastCharPos: number;
|
||||
let lastCharPos: number | undefined;
|
||||
if (line + 1 >= lineStarts.length) {
|
||||
lastCharPos = this.getEnd();
|
||||
}
|
||||
@@ -723,7 +730,7 @@ namespace ts {
|
||||
// Handle named exports case e.g.:
|
||||
// export {a, b as B} from "mod";
|
||||
if ((<ExportDeclaration>node).exportClause) {
|
||||
forEach((<ExportDeclaration>node).exportClause.elements, visit);
|
||||
forEach((<ExportDeclaration>node).exportClause!.elements, visit);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -829,7 +836,7 @@ namespace ts {
|
||||
return !s.length || s.charAt(0) === s.charAt(0).toLowerCase();
|
||||
}
|
||||
|
||||
export function displayPartsToString(displayParts: SymbolDisplayPart[]) {
|
||||
export function displayPartsToString(displayParts: SymbolDisplayPart[] | undefined) {
|
||||
if (displayParts) {
|
||||
return map(displayParts, displayPart => displayPart.text).join("");
|
||||
}
|
||||
@@ -913,7 +920,7 @@ namespace ts {
|
||||
|
||||
public getOrCreateEntryByPath(fileName: string, path: Path): HostFileInformation {
|
||||
const info = this.getEntryByPath(path) || this.createEntry(fileName, path);
|
||||
return isString(info) ? undefined : info;
|
||||
return isString(info) ? undefined! : info; // TODO: GH#18217
|
||||
}
|
||||
|
||||
public getRootFileNames(): string[] {
|
||||
@@ -933,12 +940,12 @@ namespace ts {
|
||||
|
||||
public getVersion(path: Path): string {
|
||||
const file = this.getHostFileInformation(path);
|
||||
return file && file.version;
|
||||
return (file && file.version)!; // TODO: GH#18217
|
||||
}
|
||||
|
||||
public getScriptSnapshot(path: Path): IScriptSnapshot {
|
||||
const file = this.getHostFileInformation(path);
|
||||
return file && file.scriptSnapshot;
|
||||
return (file && file.scriptSnapshot)!; // TODO: GH#18217
|
||||
}
|
||||
}
|
||||
|
||||
@@ -962,7 +969,7 @@ namespace ts {
|
||||
|
||||
const scriptKind = getScriptKind(fileName, this.host);
|
||||
const version = this.host.getScriptVersion(fileName);
|
||||
let sourceFile: SourceFile;
|
||||
let sourceFile: SourceFile | undefined;
|
||||
|
||||
if (this.currentFileName !== fileName) {
|
||||
// This is a new file, just parse it
|
||||
@@ -999,7 +1006,7 @@ namespace ts {
|
||||
|
||||
export let disableIncrementalParsing = false;
|
||||
|
||||
export function updateLanguageServiceSourceFile(sourceFile: SourceFile, scriptSnapshot: IScriptSnapshot, version: string, textChangeRange: TextChangeRange, aggressiveChecks?: boolean): SourceFile {
|
||||
export function updateLanguageServiceSourceFile(sourceFile: SourceFile, scriptSnapshot: IScriptSnapshot, version: string, textChangeRange: TextChangeRange | undefined, aggressiveChecks?: boolean): SourceFile {
|
||||
// If we were given a text change range, and our version or open-ness changed, then
|
||||
// incrementally parse this file.
|
||||
if (textChangeRange) {
|
||||
@@ -1058,11 +1065,11 @@ namespace ts {
|
||||
}
|
||||
|
||||
class CancellationTokenObject implements CancellationToken {
|
||||
constructor(private cancellationToken: HostCancellationToken) {
|
||||
constructor(private cancellationToken: HostCancellationToken | undefined) {
|
||||
}
|
||||
|
||||
public isCancellationRequested() {
|
||||
return this.cancellationToken && this.cancellationToken.isCancellationRequested();
|
||||
public isCancellationRequested(): boolean {
|
||||
return !!this.cancellationToken && this.cancellationToken.isCancellationRequested();
|
||||
}
|
||||
|
||||
public throwIfCancellationRequested(): void {
|
||||
@@ -1108,7 +1115,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
export function createSourceFileLikeCache(host: { readFile?: (path: string) => string, fileExists?: (path: string) => boolean }): SourceFileLikeCache {
|
||||
export function createSourceFileLikeCache(host: { readFile?: (path: string) => string | undefined, fileExists?: (path: string) => boolean }): SourceFileLikeCache {
|
||||
const cached = createMap<SourceFileLike>();
|
||||
return {
|
||||
get(path: Path) {
|
||||
@@ -1117,7 +1124,7 @@ namespace ts {
|
||||
}
|
||||
if (!host.fileExists || !host.readFile || !host.fileExists(path)) return;
|
||||
// And failing that, check the disk
|
||||
const text = host.readFile(path);
|
||||
const text = host.readFile(path)!; // TODO: GH#18217
|
||||
const file: SourceFileLike = {
|
||||
text,
|
||||
lineMap: undefined,
|
||||
@@ -1186,7 +1193,7 @@ namespace ts {
|
||||
const typeRootsVersion = host.getTypeRootsVersion ? host.getTypeRootsVersion() : 0;
|
||||
if (lastTypesRootVersion !== typeRootsVersion) {
|
||||
log("TypeRoots version has changed; provide new program");
|
||||
program = undefined;
|
||||
program = undefined!; // TODO: GH#18217
|
||||
lastTypesRootVersion = typeRootsVersion;
|
||||
}
|
||||
|
||||
@@ -1197,7 +1204,7 @@ namespace ts {
|
||||
const hasInvalidatedResolution: HasInvalidatedResolution = host.hasInvalidatedResolution || returnFalse;
|
||||
|
||||
// If the program is already up-to-date, we can reuse it
|
||||
if (isProgramUptoDate(program, rootFileNames, hostCache.compilationSettings(), path => hostCache.getVersion(path), fileExists, hasInvalidatedResolution, host.hasChangedAutomaticTypeDirectiveNames)) {
|
||||
if (isProgramUptoDate(program, rootFileNames, hostCache.compilationSettings(), path => hostCache.getVersion(path), fileExists, hasInvalidatedResolution, !!host.hasChangedAutomaticTypeDirectiveNames)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1230,7 +1237,7 @@ namespace ts {
|
||||
}
|
||||
return host.readFile && host.readFile(fileName);
|
||||
},
|
||||
realpath: host.realpath && (path => host.realpath(path)),
|
||||
realpath: host.realpath && (path => host.realpath!(path)),
|
||||
directoryExists: directoryName => {
|
||||
return directoryProbablyExists(directoryName, host);
|
||||
},
|
||||
@@ -1242,15 +1249,15 @@ namespace ts {
|
||||
hasChangedAutomaticTypeDirectiveNames: host.hasChangedAutomaticTypeDirectiveNames
|
||||
};
|
||||
if (host.trace) {
|
||||
compilerHost.trace = message => host.trace(message);
|
||||
compilerHost.trace = message => host.trace!(message);
|
||||
}
|
||||
|
||||
if (host.resolveModuleNames) {
|
||||
compilerHost.resolveModuleNames = (moduleNames, containingFile, reusedNames) => host.resolveModuleNames(moduleNames, containingFile, reusedNames);
|
||||
compilerHost.resolveModuleNames = (moduleNames, containingFile, reusedNames) => host.resolveModuleNames!(moduleNames, containingFile, reusedNames);
|
||||
}
|
||||
if (host.resolveTypeReferenceDirectives) {
|
||||
compilerHost.resolveTypeReferenceDirectives = (typeReferenceDirectiveNames, containingFile) => {
|
||||
return host.resolveTypeReferenceDirectives(typeReferenceDirectiveNames, containingFile);
|
||||
return host.resolveTypeReferenceDirectives!(typeReferenceDirectiveNames, containingFile);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1266,7 +1273,7 @@ namespace ts {
|
||||
|
||||
// hostCache is captured in the closure for 'getOrCreateSourceFile' but it should not be used past this point.
|
||||
// It needs to be cleared to allow all collected snapshots to be released
|
||||
hostCache = undefined;
|
||||
hostCache = undefined!;
|
||||
|
||||
// We reset this cache on structure invalidation so we don't hold on to outdated files for long; however we can't use the `compilerHost` above,
|
||||
// Because it only functions until `hostCache` is cleared, while we'll potentially need the functionality to lazily read sourcemap files during
|
||||
@@ -1278,12 +1285,12 @@ namespace ts {
|
||||
program.getTypeChecker();
|
||||
return;
|
||||
|
||||
function fileExists(fileName: string) {
|
||||
function fileExists(fileName: string): boolean {
|
||||
const path = toPath(fileName, currentDirectory, getCanonicalFileName);
|
||||
const entry = hostCache.getEntryByPath(path);
|
||||
return entry ?
|
||||
!isString(entry) :
|
||||
(host.fileExists && host.fileExists(fileName));
|
||||
(!!host.fileExists && host.fileExists(fileName));
|
||||
}
|
||||
|
||||
// Release any files we have acquired in the old program but are
|
||||
@@ -1293,11 +1300,11 @@ namespace ts {
|
||||
documentRegistry.releaseDocumentWithKey(oldSourceFile.path, oldSettingsKey);
|
||||
}
|
||||
|
||||
function getOrCreateSourceFile(fileName: string, languageVersion: ScriptTarget, onError?: (message: string) => void, shouldCreateNewSourceFile?: boolean): SourceFile {
|
||||
function getOrCreateSourceFile(fileName: string, languageVersion: ScriptTarget, onError?: (message: string) => void, shouldCreateNewSourceFile?: boolean): SourceFile | undefined {
|
||||
return getOrCreateSourceFileByPath(fileName, toPath(fileName, currentDirectory, getCanonicalFileName), languageVersion, onError, shouldCreateNewSourceFile);
|
||||
}
|
||||
|
||||
function getOrCreateSourceFileByPath(fileName: string, path: Path, _languageVersion: ScriptTarget, _onError?: (message: string) => void, shouldCreateNewSourceFile?: boolean): SourceFile {
|
||||
function getOrCreateSourceFileByPath(fileName: string, path: Path, _languageVersion: ScriptTarget, _onError?: (message: string) => void, shouldCreateNewSourceFile?: boolean): SourceFile | undefined {
|
||||
Debug.assert(hostCache !== undefined);
|
||||
// The program is asking for this file, check first if the host can locate it.
|
||||
// If the host can not locate the file, then it does not exist. return undefined
|
||||
@@ -1352,7 +1359,8 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
function getProgram(): Program {
|
||||
// TODO: GH#18217 frequently asserted as defined
|
||||
function getProgram(): Program | undefined {
|
||||
if (syntaxOnly) {
|
||||
Debug.assert(program === undefined);
|
||||
return undefined;
|
||||
@@ -1364,16 +1372,16 @@ namespace ts {
|
||||
}
|
||||
|
||||
function cleanupSemanticCache(): void {
|
||||
program = undefined;
|
||||
program = undefined!; // TODO: GH#18217
|
||||
}
|
||||
|
||||
function dispose(): void {
|
||||
if (program) {
|
||||
forEach(program.getSourceFiles(), f =>
|
||||
documentRegistry.releaseDocument(f.fileName, program.getCompilerOptions()));
|
||||
program = undefined;
|
||||
program = undefined!; // TODO: GH#18217
|
||||
}
|
||||
host = undefined;
|
||||
host = undefined!;
|
||||
}
|
||||
|
||||
/// Diagnostics
|
||||
@@ -1415,7 +1423,7 @@ namespace ts {
|
||||
return [...program.getOptionsDiagnostics(cancellationToken), ...program.getGlobalDiagnostics(cancellationToken)];
|
||||
}
|
||||
|
||||
function getCompletionsAtPosition(fileName: string, position: number, options: GetCompletionsAtPositionOptions = defaultPreferences): CompletionInfo {
|
||||
function getCompletionsAtPosition(fileName: string, position: number, options: GetCompletionsAtPositionOptions = defaultPreferences): CompletionInfo | undefined {
|
||||
// Convert from deprecated options names to new names
|
||||
const fullPreferences: UserPreferences = {
|
||||
...identity<UserPreferences>(options), // avoid excess property check
|
||||
@@ -1433,7 +1441,7 @@ namespace ts {
|
||||
options.triggerCharacter);
|
||||
}
|
||||
|
||||
function getCompletionEntryDetails(fileName: string, position: number, name: string, formattingOptions: FormatCodeSettings | undefined, source: string | undefined, preferences: UserPreferences = defaultPreferences): CompletionEntryDetails {
|
||||
function getCompletionEntryDetails(fileName: string, position: number, name: string, formattingOptions: FormatCodeSettings | undefined, source: string | undefined, preferences: UserPreferences = defaultPreferences): CompletionEntryDetails | undefined {
|
||||
synchronizeHostData();
|
||||
return Completions.getCompletionEntryDetails(
|
||||
program,
|
||||
@@ -1442,19 +1450,19 @@ namespace ts {
|
||||
position,
|
||||
{ name, source },
|
||||
host,
|
||||
formattingOptions && formatting.getFormatContext(formattingOptions),
|
||||
(formattingOptions && formatting.getFormatContext(formattingOptions))!, // TODO: GH#18217
|
||||
getCanonicalFileName,
|
||||
preferences,
|
||||
cancellationToken,
|
||||
);
|
||||
}
|
||||
|
||||
function getCompletionEntrySymbol(fileName: string, position: number, name: string, source?: string): Symbol {
|
||||
function getCompletionEntrySymbol(fileName: string, position: number, name: string, source?: string): Symbol | undefined {
|
||||
synchronizeHostData();
|
||||
return Completions.getCompletionEntrySymbol(program, log, getValidSourceFile(fileName), position, { name, source });
|
||||
}
|
||||
|
||||
function getQuickInfoAtPosition(fileName: string, position: number): QuickInfo {
|
||||
function getQuickInfoAtPosition(fileName: string, position: number): QuickInfo | undefined {
|
||||
synchronizeHostData();
|
||||
|
||||
const sourceFile = getValidSourceFile(fileName);
|
||||
@@ -1524,7 +1532,7 @@ namespace ts {
|
||||
|
||||
function toLineColumnOffset(fileName: string, position: number) {
|
||||
const path = toPath(fileName, currentDirectory, getCanonicalFileName);
|
||||
const file = program.getSourceFile(path) || sourcemappedFileCache.get(path);
|
||||
const file = program.getSourceFile(path) || sourcemappedFileCache.get(path)!; // TODO: GH#18217
|
||||
return file.getLineAndCharacterOfPosition(position);
|
||||
}
|
||||
|
||||
@@ -1547,7 +1555,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
function convertDocumentToSourceMapper(file: { sourceMapper?: sourcemaps.SourceMapper }, contents: string, mapFileName: string) {
|
||||
let maps: sourcemaps.SourceMapData;
|
||||
let maps: sourcemaps.SourceMapData | undefined;
|
||||
try {
|
||||
maps = JSON.parse(contents);
|
||||
}
|
||||
@@ -1559,8 +1567,8 @@ namespace ts {
|
||||
return file.sourceMapper = sourcemaps.identitySourceMapper;
|
||||
}
|
||||
return file.sourceMapper = sourcemaps.decode({
|
||||
readFile: s => host.readFile(s),
|
||||
fileExists: s => host.fileExists(s),
|
||||
readFile: s => host.readFile!(s), // TODO: GH#18217
|
||||
fileExists: s => host.fileExists!(s), // TODO: GH#18217
|
||||
getCanonicalFileName,
|
||||
log,
|
||||
}, mapFileName, maps, program, sourcemappedFileCache);
|
||||
@@ -1593,7 +1601,7 @@ namespace ts {
|
||||
for (const location of possibleMapLocations) {
|
||||
const mapPath = toPath(location, getDirectoryPath(fileName), getCanonicalFileName);
|
||||
if (host.fileExists(mapPath)) {
|
||||
return convertDocumentToSourceMapper(file, host.readFile(mapPath), mapPath);
|
||||
return convertDocumentToSourceMapper(file, host.readFile(mapPath)!, mapPath); // TODO: GH#18217
|
||||
}
|
||||
}
|
||||
return file.sourceMapper = sourcemaps.identitySourceMapper;
|
||||
@@ -1607,7 +1615,7 @@ namespace ts {
|
||||
function getTargetOfMappedPosition(input: TIn, original = input): TIn {
|
||||
const info = extract(input);
|
||||
if (endsWith(info.fileName, Extension.Dts)) {
|
||||
let file: SourceFileLike = program.getSourceFile(info.fileName);
|
||||
let file: SourceFileLike | undefined = program.getSourceFile(info.fileName);
|
||||
if (!file) {
|
||||
const path = toPath(info.fileName, currentDirectory, getCanonicalFileName);
|
||||
file = sourcemappedFileCache.get(path);
|
||||
@@ -1641,17 +1649,17 @@ namespace ts {
|
||||
})
|
||||
);
|
||||
|
||||
function getTargetOfMappedDeclarationFiles(infos: ReadonlyArray<DefinitionInfo>): DefinitionInfo[] {
|
||||
function getTargetOfMappedDeclarationFiles(infos: ReadonlyArray<DefinitionInfo> | undefined): DefinitionInfo[] | undefined {
|
||||
return map(infos, d => getTargetOfMappedDeclarationInfo(d));
|
||||
}
|
||||
|
||||
/// Goto definition
|
||||
function getDefinitionAtPosition(fileName: string, position: number): DefinitionInfo[] {
|
||||
function getDefinitionAtPosition(fileName: string, position: number): DefinitionInfo[] | undefined {
|
||||
synchronizeHostData();
|
||||
return getTargetOfMappedDeclarationFiles(GoToDefinition.getDefinitionAtPosition(program, getValidSourceFile(fileName), position));
|
||||
}
|
||||
|
||||
function getDefinitionAndBoundSpan(fileName: string, position: number): DefinitionInfoAndBoundSpan {
|
||||
function getDefinitionAndBoundSpan(fileName: string, position: number): DefinitionInfoAndBoundSpan | undefined {
|
||||
synchronizeHostData();
|
||||
const result = GoToDefinition.getDefinitionAndBoundSpan(program, getValidSourceFile(fileName), position);
|
||||
if (!result) return result;
|
||||
@@ -1665,7 +1673,7 @@ namespace ts {
|
||||
};
|
||||
}
|
||||
|
||||
function getTypeDefinitionAtPosition(fileName: string, position: number): DefinitionInfo[] {
|
||||
function getTypeDefinitionAtPosition(fileName: string, position: number): DefinitionInfo[] | undefined {
|
||||
synchronizeHostData();
|
||||
return getTargetOfMappedDeclarationFiles(GoToDefinition.getTypeDefinitionAtPosition(program.getTypeChecker(), getValidSourceFile(fileName), position));
|
||||
}
|
||||
@@ -1687,17 +1695,17 @@ namespace ts {
|
||||
})
|
||||
);
|
||||
|
||||
function getTargetOfMappedImplementationLocations(infos: ReadonlyArray<ImplementationLocation>): ImplementationLocation[] {
|
||||
function getTargetOfMappedImplementationLocations(infos: ReadonlyArray<ImplementationLocation> | undefined): ImplementationLocation[] | undefined {
|
||||
return map(infos, d => getTargetOfMappedImplementationLocation(d));
|
||||
}
|
||||
|
||||
function getImplementationAtPosition(fileName: string, position: number): ImplementationLocation[] {
|
||||
function getImplementationAtPosition(fileName: string, position: number): ImplementationLocation[] | undefined {
|
||||
synchronizeHostData();
|
||||
return getTargetOfMappedImplementationLocations(FindAllReferences.getImplementationsAtPosition(program, cancellationToken, program.getSourceFiles(), getValidSourceFile(fileName), position));
|
||||
}
|
||||
|
||||
/// References and Occurrences
|
||||
function getOccurrencesAtPosition(fileName: string, position: number): ReferenceEntry[] {
|
||||
function getOccurrencesAtPosition(fileName: string, position: number): ReferenceEntry[] | undefined {
|
||||
return flatMap(getDocumentHighlights(fileName, position, [fileName]), entry => entry.highlightSpans.map<ReferenceEntry>(highlightSpan => ({
|
||||
fileName: entry.fileName,
|
||||
textSpan: highlightSpan.textSpan,
|
||||
@@ -1707,7 +1715,7 @@ namespace ts {
|
||||
})));
|
||||
}
|
||||
|
||||
function getDocumentHighlights(fileName: string, position: number, filesToSearch: ReadonlyArray<string>): DocumentHighlights[] {
|
||||
function getDocumentHighlights(fileName: string, position: number, filesToSearch: ReadonlyArray<string>): DocumentHighlights[] | undefined {
|
||||
Debug.assert(filesToSearch.some(f => normalizePath(f) === fileName));
|
||||
synchronizeHostData();
|
||||
const sourceFilesToSearch = map(filesToSearch, f => Debug.assertDefined(program.getSourceFile(f)));
|
||||
@@ -1715,15 +1723,15 @@ namespace ts {
|
||||
return DocumentHighlights.getDocumentHighlights(program, cancellationToken, sourceFile, position, sourceFilesToSearch);
|
||||
}
|
||||
|
||||
function findRenameLocations(fileName: string, position: number, findInStrings: boolean, findInComments: boolean): RenameLocation[] {
|
||||
function findRenameLocations(fileName: string, position: number, findInStrings: boolean, findInComments: boolean): RenameLocation[] | undefined {
|
||||
return getReferences(fileName, position, { findInStrings, findInComments, isForRename: true });
|
||||
}
|
||||
|
||||
function getReferencesAtPosition(fileName: string, position: number): ReferenceEntry[] {
|
||||
return getReferences(fileName, position);
|
||||
function getReferencesAtPosition(fileName: string, position: number): ReferenceEntry[] | undefined {
|
||||
return getReferences(fileName, position)!;
|
||||
}
|
||||
|
||||
function getReferences(fileName: string, position: number, options?: FindAllReferences.Options) {
|
||||
function getReferences(fileName: string, position: number, options?: FindAllReferences.Options): ReferenceEntry[] | undefined {
|
||||
synchronizeHostData();
|
||||
|
||||
// Exclude default library when renaming as commonly user don't want to change that file.
|
||||
@@ -1742,20 +1750,20 @@ namespace ts {
|
||||
return FindAllReferences.findReferencedEntries(program, cancellationToken, sourceFiles, getValidSourceFile(fileName), position, options);
|
||||
}
|
||||
|
||||
function findReferences(fileName: string, position: number): ReferencedSymbol[] {
|
||||
function findReferences(fileName: string, position: number): ReferencedSymbol[] | undefined {
|
||||
synchronizeHostData();
|
||||
return FindAllReferences.findReferencedSymbols(program, cancellationToken, program.getSourceFiles(), getValidSourceFile(fileName), position);
|
||||
}
|
||||
|
||||
/// NavigateTo
|
||||
function getNavigateToItems(searchValue: string, maxResultCount?: number, fileName?: string, excludeDtsFiles?: boolean): NavigateToItem[] {
|
||||
function getNavigateToItems(searchValue: string, maxResultCount?: number, fileName?: string, excludeDtsFiles = false): NavigateToItem[] {
|
||||
synchronizeHostData();
|
||||
|
||||
const sourceFiles = fileName ? [getValidSourceFile(fileName)] : program.getSourceFiles();
|
||||
return NavigateTo.getNavigateToItems(sourceFiles, program.getTypeChecker(), cancellationToken, searchValue, maxResultCount, excludeDtsFiles);
|
||||
}
|
||||
|
||||
function getEmitOutput(fileName: string, emitOnlyDtsFiles?: boolean) {
|
||||
function getEmitOutput(fileName: string, emitOnlyDtsFiles = false) {
|
||||
synchronizeHostData();
|
||||
|
||||
const sourceFile = getValidSourceFile(fileName);
|
||||
@@ -1767,7 +1775,7 @@ namespace ts {
|
||||
/**
|
||||
* This is a semantic operation.
|
||||
*/
|
||||
function getSignatureHelpItems(fileName: string, position: number): SignatureHelpItems {
|
||||
function getSignatureHelpItems(fileName: string, position: number): SignatureHelpItems | undefined {
|
||||
synchronizeHostData();
|
||||
|
||||
const sourceFile = getValidSourceFile(fileName);
|
||||
@@ -1784,14 +1792,14 @@ namespace ts {
|
||||
return getNonBoundSourceFile(fileName);
|
||||
}
|
||||
|
||||
function getNameOrDottedNameSpan(fileName: string, startPos: number, _endPos: number): TextSpan {
|
||||
function getNameOrDottedNameSpan(fileName: string, startPos: number, _endPos: number): TextSpan | undefined {
|
||||
const sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName);
|
||||
|
||||
// Get node at the location
|
||||
const node = getTouchingPropertyName(sourceFile, startPos, /*includeJsDocComment*/ false);
|
||||
|
||||
if (node === sourceFile) {
|
||||
return;
|
||||
return undefined;
|
||||
}
|
||||
|
||||
switch (node.kind) {
|
||||
@@ -1809,7 +1817,7 @@ namespace ts {
|
||||
|
||||
// Cant create the text span
|
||||
default:
|
||||
return;
|
||||
return undefined;
|
||||
}
|
||||
|
||||
let nodeForStartPos = node;
|
||||
@@ -1841,7 +1849,7 @@ namespace ts {
|
||||
return createTextSpanFromBounds(nodeForStartPos.getStart(), node.getEnd());
|
||||
}
|
||||
|
||||
function getBreakpointStatementAtPosition(fileName: string, position: number) {
|
||||
function getBreakpointStatementAtPosition(fileName: string, position: number): TextSpan | undefined {
|
||||
// doesn't use compiler - no need to synchronize with host
|
||||
const sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName);
|
||||
|
||||
@@ -1986,7 +1994,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
function getEditsForFileRename(oldFilePath: string, newFilePath: string, formatOptions: FormatCodeSettings): ReadonlyArray<FileTextChanges> {
|
||||
return ts.getEditsForFileRename(getProgram(), oldFilePath, newFilePath, host, formatting.getFormatContext(formatOptions));
|
||||
return ts.getEditsForFileRename(getProgram()!, oldFilePath, newFilePath, host, formatting.getFormatContext(formatOptions));
|
||||
}
|
||||
|
||||
function applyCodeActionCommand(action: CodeActionCommand): Promise<ApplyCodeActionCommandResult>;
|
||||
@@ -2006,7 +2014,7 @@ namespace ts {
|
||||
? host.installPackage({ fileName: toPath(action.file, currentDirectory, getCanonicalFileName), packageName: action.packageName })
|
||||
: Promise.reject("Host does not implement `installPackage`");
|
||||
default:
|
||||
Debug.fail();
|
||||
return Debug.fail();
|
||||
// TODO: Debug.assertNever(action); will only work if there is more than one type.
|
||||
}
|
||||
}
|
||||
@@ -2051,7 +2059,7 @@ namespace ts {
|
||||
return true;
|
||||
}
|
||||
|
||||
function getSpanOfEnclosingComment(fileName: string, position: number, onlyMultiLine: boolean) {
|
||||
function getSpanOfEnclosingComment(fileName: string, position: number, onlyMultiLine: boolean): TextSpan | undefined {
|
||||
const sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName);
|
||||
const range = formatting.getRangeOfEnclosingComment(sourceFile, position, onlyMultiLine);
|
||||
return range && createTextSpanFromRange(range);
|
||||
@@ -2077,7 +2085,7 @@ namespace ts {
|
||||
if (descriptors.length > 0 && !isNodeModulesFile(sourceFile.fileName)) {
|
||||
const regExp = getTodoCommentsRegExp();
|
||||
|
||||
let matchArray: RegExpExecArray;
|
||||
let matchArray: RegExpExecArray | null;
|
||||
while (matchArray = regExp.exec(fileContents)) {
|
||||
cancellationToken.throwIfCancellationRequested();
|
||||
|
||||
@@ -2110,13 +2118,13 @@ namespace ts {
|
||||
continue;
|
||||
}
|
||||
|
||||
let descriptor: TodoCommentDescriptor;
|
||||
let descriptor: TodoCommentDescriptor | undefined;
|
||||
for (let i = 0; i < descriptors.length; i++) {
|
||||
if (matchArray[i + firstDescriptorCaptureIndex]) {
|
||||
descriptor = descriptors[i];
|
||||
}
|
||||
}
|
||||
Debug.assert(descriptor !== undefined);
|
||||
if (descriptor === undefined) return Debug.fail();
|
||||
|
||||
// We don't want to match something like 'TODOBY', so we make sure a non
|
||||
// letter/digit follows the match.
|
||||
@@ -2216,9 +2224,9 @@ namespace ts {
|
||||
file,
|
||||
startPosition,
|
||||
endPosition,
|
||||
program: getProgram(),
|
||||
program: getProgram()!,
|
||||
host,
|
||||
formatContext: formatting.getFormatContext(formatOptions),
|
||||
formatContext: formatting.getFormatContext(formatOptions!), // TODO: GH#18217
|
||||
cancellationToken,
|
||||
preferences,
|
||||
};
|
||||
@@ -2237,8 +2245,7 @@ namespace ts {
|
||||
refactorName: string,
|
||||
actionName: string,
|
||||
preferences: UserPreferences = defaultPreferences,
|
||||
): RefactorEditInfo {
|
||||
|
||||
): RefactorEditInfo | undefined {
|
||||
synchronizeHostData();
|
||||
const file = getValidSourceFile(fileName);
|
||||
return refactor.getEditsForRefactor(getRefactorContext(file, positionOrRange, preferences, formatOptions), refactorName, actionName);
|
||||
@@ -2307,7 +2314,7 @@ namespace ts {
|
||||
initializeNameTable(sourceFile);
|
||||
}
|
||||
|
||||
return sourceFile.nameTable;
|
||||
return sourceFile.nameTable!; // TODO: GH#18217
|
||||
}
|
||||
|
||||
function initializeNameTable(sourceFile: SourceFile): void {
|
||||
@@ -2320,7 +2327,7 @@ namespace ts {
|
||||
|
||||
forEachChild(node, walk);
|
||||
if (hasJSDocNodes(node)) {
|
||||
for (const jsDoc of node.jsDoc) {
|
||||
for (const jsDoc of node.jsDoc!) {
|
||||
forEachChild(jsDoc, walk);
|
||||
}
|
||||
}
|
||||
@@ -2344,7 +2351,7 @@ namespace ts {
|
||||
* Returns the containing object literal property declaration given a possible name node, e.g. "a" in x = { "a": 1 }
|
||||
*/
|
||||
/* @internal */
|
||||
export function getContainingObjectLiteralElement(node: Node): ObjectLiteralElement {
|
||||
export function getContainingObjectLiteralElement(node: Node): ObjectLiteralElement | undefined {
|
||||
switch (node.kind) {
|
||||
case SyntaxKind.StringLiteral:
|
||||
case SyntaxKind.NumericLiteral:
|
||||
@@ -2363,8 +2370,8 @@ namespace ts {
|
||||
/* @internal */
|
||||
export function getPropertySymbolsFromContextualType(typeChecker: TypeChecker, node: ObjectLiteralElement): Symbol[] {
|
||||
const objectLiteral = <ObjectLiteralExpression | JsxAttributes>node.parent;
|
||||
const contextualType = typeChecker.getContextualType(objectLiteral);
|
||||
return getPropertySymbolsFromType(contextualType, node.name);
|
||||
const contextualType = typeChecker.getContextualType(objectLiteral)!; // TODO: GH#18217
|
||||
return getPropertySymbolsFromType(contextualType, node.name!)!; // TODO: GH#18217
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
|
||||
+26
-26
@@ -306,14 +306,14 @@ namespace ts {
|
||||
return this.scriptSnapshotShim.getLength();
|
||||
}
|
||||
|
||||
public getChangeRange(oldSnapshot: IScriptSnapshot): TextChangeRange {
|
||||
public getChangeRange(oldSnapshot: IScriptSnapshot): TextChangeRange | undefined {
|
||||
const oldSnapshotShim = <ScriptSnapshotShimAdapter>oldSnapshot;
|
||||
const encoded = this.scriptSnapshotShim.getChangeRange(oldSnapshotShim.scriptSnapshotShim);
|
||||
if (encoded === null) {
|
||||
return null;
|
||||
return null!; // TODO: GH#18217
|
||||
}
|
||||
|
||||
const decoded: { span: { start: number; length: number; }; newLength: number; } = JSON.parse(encoded);
|
||||
const decoded: { span: { start: number; length: number; }; newLength: number; } = JSON.parse(encoded!); // TODO: GH#18217
|
||||
return createTextChangeRange(
|
||||
createTextSpan(decoded.span.start, decoded.span.length), decoded.newLength);
|
||||
}
|
||||
@@ -322,7 +322,7 @@ namespace ts {
|
||||
// if scriptSnapshotShim is a COM object then property check becomes method call with no arguments
|
||||
// 'in' does not have this effect
|
||||
if ("dispose" in this.scriptSnapshotShim) {
|
||||
this.scriptSnapshotShim.dispose();
|
||||
this.scriptSnapshotShim.dispose!(); // TODO: GH#18217 Can we just use `if (this.scriptSnapshotShim.dispose)`?
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -341,10 +341,10 @@ namespace ts {
|
||||
// 'in' does not have this effect.
|
||||
if ("getModuleResolutionsForFile" in this.shimHost) {
|
||||
this.resolveModuleNames = (moduleNames: string[], containingFile: string): ResolvedModuleFull[] => {
|
||||
const resolutionsInFile = <MapLike<string>>JSON.parse(this.shimHost.getModuleResolutionsForFile(containingFile));
|
||||
const resolutionsInFile = <MapLike<string>>JSON.parse(this.shimHost.getModuleResolutionsForFile!(containingFile)); // TODO: GH#18217
|
||||
return map(moduleNames, name => {
|
||||
const result = getProperty(resolutionsInFile, name);
|
||||
return result ? { resolvedFileName: result, extension: extensionFromPath(result), isExternalLibraryImport: false } : undefined;
|
||||
return result ? { resolvedFileName: result, extension: extensionFromPath(result), isExternalLibraryImport: false } : undefined!; // TODO: GH#18217
|
||||
});
|
||||
};
|
||||
}
|
||||
@@ -353,8 +353,8 @@ namespace ts {
|
||||
}
|
||||
if ("getTypeReferenceDirectiveResolutionsForFile" in this.shimHost) {
|
||||
this.resolveTypeReferenceDirectives = (typeDirectiveNames: string[], containingFile: string) => {
|
||||
const typeDirectivesForFile = <MapLike<ResolvedTypeReferenceDirective>>JSON.parse(this.shimHost.getTypeReferenceDirectiveResolutionsForFile(containingFile));
|
||||
return map(typeDirectiveNames, name => getProperty(typeDirectivesForFile, name));
|
||||
const typeDirectivesForFile = <MapLike<ResolvedTypeReferenceDirective>>JSON.parse(this.shimHost.getTypeReferenceDirectiveResolutionsForFile!(containingFile)); // TODO: GH#18217
|
||||
return map(typeDirectiveNames, name => getProperty(typeDirectivesForFile, name)!); // TODO: GH#18217
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -378,7 +378,7 @@ namespace ts {
|
||||
public getProjectVersion(): string {
|
||||
if (!this.shimHost.getProjectVersion) {
|
||||
// shimmed host does not support getProjectVersion
|
||||
return undefined;
|
||||
return undefined!; // TODO: GH#18217
|
||||
}
|
||||
|
||||
return this.shimHost.getProjectVersion();
|
||||
@@ -411,14 +411,14 @@ namespace ts {
|
||||
return this.files = JSON.parse(encoded);
|
||||
}
|
||||
|
||||
public getScriptSnapshot(fileName: string): IScriptSnapshot {
|
||||
public getScriptSnapshot(fileName: string): IScriptSnapshot | undefined {
|
||||
const scriptSnapshot = this.shimHost.getScriptSnapshot(fileName);
|
||||
return scriptSnapshot && new ScriptSnapshotShimAdapter(scriptSnapshot);
|
||||
}
|
||||
|
||||
public getScriptKind(fileName: string): ScriptKind {
|
||||
if ("getScriptKind" in this.shimHost) {
|
||||
return this.shimHost.getScriptKind(fileName);
|
||||
return this.shimHost.getScriptKind!(fileName); // TODO: GH#18217
|
||||
}
|
||||
else {
|
||||
return ScriptKind.Unknown;
|
||||
@@ -463,7 +463,7 @@ namespace ts {
|
||||
|
||||
public readDirectory(path: string, extensions?: ReadonlyArray<string>, exclude?: string[], include?: string[], depth?: number): string[] {
|
||||
const pattern = getFileMatcherPatterns(path, exclude, include,
|
||||
this.shimHost.useCaseSensitiveFileNames(), this.shimHost.getCurrentDirectory());
|
||||
this.shimHost.useCaseSensitiveFileNames!(), this.shimHost.getCurrentDirectory()); // TODO: GH#18217
|
||||
return JSON.parse(this.shimHost.readDirectory(
|
||||
path,
|
||||
JSON.stringify(extensions),
|
||||
@@ -496,13 +496,13 @@ namespace ts {
|
||||
this.directoryExists = directoryName => this.shimHost.directoryExists(directoryName);
|
||||
}
|
||||
if ("realpath" in this.shimHost) {
|
||||
this.realpath = path => this.shimHost.realpath(path);
|
||||
this.realpath = path => this.shimHost.realpath!(path); // TODO: GH#18217
|
||||
}
|
||||
}
|
||||
|
||||
public readDirectory(rootDir: string, extensions: ReadonlyArray<string>, exclude: ReadonlyArray<string>, include: ReadonlyArray<string>, depth?: number): string[] {
|
||||
const pattern = getFileMatcherPatterns(rootDir, exclude, include,
|
||||
this.shimHost.useCaseSensitiveFileNames(), this.shimHost.getCurrentDirectory());
|
||||
this.shimHost.useCaseSensitiveFileNames!(), this.shimHost.getCurrentDirectory()); // TODO: GH#18217
|
||||
return JSON.parse(this.shimHost.readDirectory(
|
||||
rootDir,
|
||||
JSON.stringify(extensions),
|
||||
@@ -528,7 +528,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
function simpleForwardCall(logger: Logger, actionDescription: string, action: () => {}, logPerformance: boolean): {} {
|
||||
let start: number;
|
||||
let start: number | undefined;
|
||||
if (logPerformance) {
|
||||
logger.log(actionDescription);
|
||||
start = timestamp();
|
||||
@@ -538,7 +538,7 @@ namespace ts {
|
||||
|
||||
if (logPerformance) {
|
||||
const end = timestamp();
|
||||
logger.log(`${actionDescription} completed in ${end - start} msec`);
|
||||
logger.log(`${actionDescription} completed in ${end - start!} msec`);
|
||||
if (isString(result)) {
|
||||
let str = result;
|
||||
if (str.length > 128) {
|
||||
@@ -551,7 +551,7 @@ namespace ts {
|
||||
return result;
|
||||
}
|
||||
|
||||
function forwardJSONCall(logger: Logger, actionDescription: string, action: () => {}, logPerformance: boolean): string {
|
||||
function forwardJSONCall(logger: Logger, actionDescription: string, action: () => {} | null | undefined, logPerformance: boolean): string {
|
||||
return <string>forwardCall(logger, actionDescription, /*returnJson*/ true, action, logPerformance);
|
||||
}
|
||||
|
||||
@@ -595,8 +595,8 @@ namespace ts {
|
||||
function realizeDiagnostic(diagnostic: Diagnostic, newLine: string): RealizedDiagnostic {
|
||||
return {
|
||||
message: flattenDiagnosticMessageText(diagnostic.messageText, newLine),
|
||||
start: diagnostic.start,
|
||||
length: diagnostic.length,
|
||||
start: diagnostic.start!, // TODO: GH#18217
|
||||
length: diagnostic.length!, // TODO: GH#18217
|
||||
category: diagnosticCategoryName(diagnostic),
|
||||
code: diagnostic.code,
|
||||
reportsUnnecessary: diagnostic.reportsUnnecessary,
|
||||
@@ -614,7 +614,7 @@ namespace ts {
|
||||
this.logger = this.host;
|
||||
}
|
||||
|
||||
public forwardJSONCall(actionDescription: string, action: () => {}): string {
|
||||
public forwardJSONCall(actionDescription: string, action: () => {} | null | undefined): string {
|
||||
return forwardJSONCall(this.logger, actionDescription, action, this.logPerformance);
|
||||
}
|
||||
|
||||
@@ -627,7 +627,7 @@ namespace ts {
|
||||
public dispose(dummy: {}): void {
|
||||
this.logger.log("dispose()");
|
||||
this.languageService.dispose();
|
||||
this.languageService = null;
|
||||
this.languageService = null!;
|
||||
|
||||
// force a GC
|
||||
if (debugObjectHost && debugObjectHost.CollectGarbage) {
|
||||
@@ -635,7 +635,7 @@ namespace ts {
|
||||
this.logger.log("CollectGarbage()");
|
||||
}
|
||||
|
||||
this.logger = null;
|
||||
this.logger = null!;
|
||||
|
||||
super.dispose(dummy);
|
||||
}
|
||||
@@ -1034,14 +1034,14 @@ namespace ts {
|
||||
this.classifier = createClassifier();
|
||||
}
|
||||
|
||||
public getEncodedLexicalClassifications(text: string, lexState: EndOfLineState, syntacticClassifierAbsent?: boolean): string {
|
||||
public getEncodedLexicalClassifications(text: string, lexState: EndOfLineState, syntacticClassifierAbsent = false): string {
|
||||
return forwardJSONCall(this.logger, "getEncodedLexicalClassifications",
|
||||
() => convertClassifications(this.classifier.getEncodedLexicalClassifications(text, lexState, syntacticClassifierAbsent)),
|
||||
this.logPerformance);
|
||||
}
|
||||
|
||||
/// COLORIZATION
|
||||
public getClassificationsForLine(text: string, lexState: EndOfLineState, classifyKeywordsInGenerics?: boolean): string {
|
||||
public getClassificationsForLine(text: string, lexState: EndOfLineState, classifyKeywordsInGenerics = false): string {
|
||||
const classification = this.classifier.getClassificationsForLine(text, lexState, classifyKeywordsInGenerics);
|
||||
let result = "";
|
||||
for (const item of classification.entries) {
|
||||
@@ -1119,7 +1119,7 @@ namespace ts {
|
||||
);
|
||||
}
|
||||
|
||||
private convertFileReferences(refs: FileReference[]): ShimsFileReference[] {
|
||||
private convertFileReferences(refs: FileReference[]): ShimsFileReference[] | undefined {
|
||||
if (!refs) {
|
||||
return undefined;
|
||||
}
|
||||
@@ -1230,7 +1230,7 @@ namespace ts {
|
||||
public close(): void {
|
||||
// Forget all the registered shims
|
||||
clear(this._shims);
|
||||
this.documentRegistry = undefined;
|
||||
this.documentRegistry = undefined!;
|
||||
}
|
||||
|
||||
public registerShim(shim: Shim): void {
|
||||
|
||||
@@ -16,7 +16,7 @@ namespace ts.SignatureHelp {
|
||||
argumentCount: number;
|
||||
}
|
||||
|
||||
export function getSignatureHelpItems(program: Program, sourceFile: SourceFile, position: number, cancellationToken: CancellationToken): SignatureHelpItems {
|
||||
export function getSignatureHelpItems(program: Program, sourceFile: SourceFile, position: number, cancellationToken: CancellationToken): SignatureHelpItems | undefined {
|
||||
const typeChecker = program.getTypeChecker();
|
||||
|
||||
// Decide whether to show signature help
|
||||
@@ -47,10 +47,10 @@ namespace ts.SignatureHelp {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return typeChecker.runWithCancellationToken(cancellationToken, typeChecker => createSignatureHelpItems(candidates, resolvedSignature, argumentInfo, typeChecker));
|
||||
return typeChecker.runWithCancellationToken(cancellationToken, typeChecker => createSignatureHelpItems(candidates, resolvedSignature!, argumentInfo, typeChecker));
|
||||
}
|
||||
|
||||
function createJavaScriptSignatureHelpItems(argumentInfo: ArgumentListInfo, program: Program, cancellationToken: CancellationToken): SignatureHelpItems {
|
||||
function createJavaScriptSignatureHelpItems(argumentInfo: ArgumentListInfo, program: Program, cancellationToken: CancellationToken): SignatureHelpItems | undefined {
|
||||
if (argumentInfo.invocation.kind !== SyntaxKind.CallExpression) {
|
||||
return undefined;
|
||||
}
|
||||
@@ -90,9 +90,9 @@ namespace ts.SignatureHelp {
|
||||
* in the argument of an invocation; returns undefined otherwise.
|
||||
*/
|
||||
export function getImmediatelyContainingArgumentInfo(node: Node, position: number, sourceFile: SourceFile): ArgumentListInfo | undefined {
|
||||
if (isCallOrNewExpression(node.parent)) {
|
||||
const invocation = node.parent;
|
||||
let list: Node;
|
||||
const { parent } = node;
|
||||
if (isCallOrNewExpression(parent)) {
|
||||
let list: Node | undefined;
|
||||
let argumentIndex: number;
|
||||
|
||||
// There are 3 cases to handle:
|
||||
@@ -112,7 +112,7 @@ namespace ts.SignatureHelp {
|
||||
if (node.kind === SyntaxKind.LessThanToken || node.kind === SyntaxKind.OpenParenToken) {
|
||||
// Find the list that starts right *after* the < or ( token.
|
||||
// If the user has just opened a list, consider this item 0.
|
||||
list = getChildListThatStartsWithOpenerToken(invocation, node, sourceFile);
|
||||
list = getChildListThatStartsWithOpenerToken(parent, node, sourceFile);
|
||||
Debug.assert(list !== undefined);
|
||||
argumentIndex = 0;
|
||||
}
|
||||
@@ -128,22 +128,22 @@ namespace ts.SignatureHelp {
|
||||
argumentIndex = getArgumentIndex(list, node);
|
||||
}
|
||||
|
||||
const kind = invocation.typeArguments && invocation.typeArguments.pos === list.pos ? ArgumentListKind.TypeArguments : ArgumentListKind.CallArguments;
|
||||
const kind = parent.typeArguments && parent.typeArguments.pos === list.pos ? ArgumentListKind.TypeArguments : ArgumentListKind.CallArguments;
|
||||
const argumentCount = getArgumentCount(list);
|
||||
if (argumentIndex !== 0) {
|
||||
Debug.assertLessThan(argumentIndex, argumentCount);
|
||||
}
|
||||
const argumentsSpan = getApplicableSpanForArguments(list, sourceFile);
|
||||
return { kind, invocation, argumentsSpan, argumentIndex, argumentCount };
|
||||
return { kind, invocation: parent, argumentsSpan, argumentIndex, argumentCount };
|
||||
}
|
||||
else if (node.kind === SyntaxKind.NoSubstitutionTemplateLiteral && node.parent.kind === SyntaxKind.TaggedTemplateExpression) {
|
||||
else if (node.kind === SyntaxKind.NoSubstitutionTemplateLiteral && parent.kind === SyntaxKind.TaggedTemplateExpression) {
|
||||
// Check if we're actually inside the template;
|
||||
// otherwise we'll fall out and return undefined.
|
||||
if (isInsideTemplateLiteral(<LiteralExpression>node, position)) {
|
||||
return getArgumentListInfoForTemplate(<TaggedTemplateExpression>node.parent, /*argumentIndex*/ 0, sourceFile);
|
||||
}
|
||||
}
|
||||
else if (node.kind === SyntaxKind.TemplateHead && node.parent.parent.kind === SyntaxKind.TaggedTemplateExpression) {
|
||||
else if (node.kind === SyntaxKind.TemplateHead && parent.parent.kind === SyntaxKind.TaggedTemplateExpression) {
|
||||
const templateExpression = <TemplateExpression>node.parent;
|
||||
const tagExpression = <TaggedTemplateExpression>templateExpression.parent;
|
||||
Debug.assert(templateExpression.kind === SyntaxKind.TemplateExpression);
|
||||
@@ -152,7 +152,7 @@ namespace ts.SignatureHelp {
|
||||
|
||||
return getArgumentListInfoForTemplate(tagExpression, argumentIndex, sourceFile);
|
||||
}
|
||||
else if (node.parent.kind === SyntaxKind.TemplateSpan && node.parent.parent.parent.kind === SyntaxKind.TaggedTemplateExpression) {
|
||||
else if (parent.kind === SyntaxKind.TemplateSpan && parent.parent.parent.kind === SyntaxKind.TaggedTemplateExpression) {
|
||||
const templateSpan = <TemplateSpan>node.parent;
|
||||
const templateExpression = templateSpan.parent;
|
||||
const tagExpression = <TaggedTemplateExpression>templateExpression.parent;
|
||||
@@ -228,7 +228,7 @@ namespace ts.SignatureHelp {
|
||||
const listChildren = argumentsList.getChildren();
|
||||
|
||||
let argumentCount = countWhere(listChildren, arg => arg.kind !== SyntaxKind.CommaToken);
|
||||
if (listChildren.length > 0 && lastOrUndefined(listChildren).kind === SyntaxKind.CommaToken) {
|
||||
if (listChildren.length > 0 && last(listChildren).kind === SyntaxKind.CommaToken) {
|
||||
argumentCount++;
|
||||
}
|
||||
|
||||
@@ -304,7 +304,7 @@ namespace ts.SignatureHelp {
|
||||
// This is because a Missing node has no width. However, what we actually want is to include trivia
|
||||
// leading up to the next token in case the user is about to type in a TemplateMiddle or TemplateTail.
|
||||
if (template.kind === SyntaxKind.TemplateExpression) {
|
||||
const lastSpan = lastOrUndefined(template.templateSpans);
|
||||
const lastSpan = last(template.templateSpans);
|
||||
if (lastSpan.literal.getFullWidth() === 0) {
|
||||
applicableSpanEnd = skipTrivia(sourceFile.text, applicableSpanEnd, /*stopAfterLineBreak*/ false);
|
||||
}
|
||||
@@ -313,7 +313,7 @@ namespace ts.SignatureHelp {
|
||||
return createTextSpan(applicableSpanStart, applicableSpanEnd - applicableSpanStart);
|
||||
}
|
||||
|
||||
export function getContainingArgumentInfo(node: Node, position: number, sourceFile: SourceFile): ArgumentListInfo {
|
||||
export function getContainingArgumentInfo(node: Node, position: number, sourceFile: SourceFile): ArgumentListInfo | undefined {
|
||||
for (let n = node; n.kind !== SyntaxKind.SourceFile; n = n.parent) {
|
||||
if (isFunctionBlock(n)) {
|
||||
return undefined;
|
||||
@@ -369,8 +369,8 @@ namespace ts.SignatureHelp {
|
||||
signatureHelpParameters = typeParameters && typeParameters.length > 0 ? map(typeParameters, createSignatureHelpParameterForTypeParameter) : emptyArray;
|
||||
suffixDisplayParts.push(punctuationPart(SyntaxKind.GreaterThanToken));
|
||||
const parameterParts = mapToDisplayParts(writer => {
|
||||
const thisParameter = candidateSignature.thisParameter ? [typeChecker.symbolToParameterDeclaration(candidateSignature.thisParameter, invocation, signatureHelpNodeBuilderFlags)] : [];
|
||||
const params = createNodeArray([...thisParameter, ...map(candidateSignature.parameters, param => typeChecker.symbolToParameterDeclaration(param, invocation, signatureHelpNodeBuilderFlags))]);
|
||||
const thisParameter = candidateSignature.thisParameter ? [typeChecker.symbolToParameterDeclaration(candidateSignature.thisParameter, invocation, signatureHelpNodeBuilderFlags)!] : [];
|
||||
const params = createNodeArray([...thisParameter, ...map(candidateSignature.parameters, param => typeChecker.symbolToParameterDeclaration(param, invocation, signatureHelpNodeBuilderFlags)!)]);
|
||||
printer.writeList(ListFormat.CallExpressionArguments, params, getSourceFileOfNode(getParseTreeNode(invocation)), writer);
|
||||
});
|
||||
addRange(suffixDisplayParts, parameterParts);
|
||||
@@ -379,7 +379,7 @@ namespace ts.SignatureHelp {
|
||||
isVariadic = candidateSignature.hasRestParameter;
|
||||
const typeParameterParts = mapToDisplayParts(writer => {
|
||||
if (candidateSignature.typeParameters && candidateSignature.typeParameters.length) {
|
||||
const args = createNodeArray(map(candidateSignature.typeParameters, p => typeChecker.typeParameterToDeclaration(p, invocation)));
|
||||
const args = createNodeArray(map(candidateSignature.typeParameters, p => typeChecker.typeParameterToDeclaration(p, invocation)!));
|
||||
printer.writeList(ListFormat.TypeParameters, args, getSourceFileOfNode(getParseTreeNode(invocation)), writer);
|
||||
}
|
||||
});
|
||||
@@ -415,17 +415,17 @@ namespace ts.SignatureHelp {
|
||||
});
|
||||
|
||||
if (argumentIndex !== 0) {
|
||||
Debug.assertLessThan(argumentIndex, argumentCount);
|
||||
Debug.assertLessThan(argumentIndex!, argumentCount); // TODO: GH#18217
|
||||
}
|
||||
|
||||
const selectedItemIndex = candidates.indexOf(resolvedSignature);
|
||||
Debug.assert(selectedItemIndex !== -1); // If candidates is non-empty it should always include bestSignature. We check for an empty candidates before calling this function.
|
||||
|
||||
return { items, applicableSpan, selectedItemIndex, argumentIndex, argumentCount };
|
||||
return { items, applicableSpan, selectedItemIndex, argumentIndex: argumentIndex!, argumentCount }; // TODO: GH#18217
|
||||
|
||||
function createSignatureHelpParameterForParameter(parameter: Symbol): SignatureHelpParameter {
|
||||
const displayParts = mapToDisplayParts(writer => {
|
||||
const param = typeChecker.symbolToParameterDeclaration(parameter, invocation, signatureHelpNodeBuilderFlags);
|
||||
const param = typeChecker.symbolToParameterDeclaration(parameter, invocation, signatureHelpNodeBuilderFlags)!;
|
||||
printer.writeNode(EmitHint.Unspecified, param, getSourceFileOfNode(getParseTreeNode(invocation)), writer);
|
||||
});
|
||||
|
||||
@@ -439,7 +439,7 @@ namespace ts.SignatureHelp {
|
||||
|
||||
function createSignatureHelpParameterForTypeParameter(typeParameter: TypeParameter): SignatureHelpParameter {
|
||||
const displayParts = mapToDisplayParts(writer => {
|
||||
const param = typeChecker.typeParameterToDeclaration(typeParameter, invocation);
|
||||
const param = typeChecker.typeParameterToDeclaration(typeParameter, invocation)!;
|
||||
printer.writeNode(EmitHint.Unspecified, param, getSourceFileOfNode(getParseTreeNode(invocation)), writer);
|
||||
});
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ namespace ts.sourcemaps {
|
||||
export const identitySourceMapper = { getOriginalPosition: identity, getGeneratedPosition: identity };
|
||||
|
||||
export interface SourceMapDecodeHost {
|
||||
readFile(path: string): string;
|
||||
readFile(path: string): string | undefined;
|
||||
fileExists(path: string): boolean;
|
||||
getCanonicalFileName(path: string): string;
|
||||
log(text: string): void;
|
||||
@@ -52,7 +52,7 @@ namespace ts.sourcemaps {
|
||||
if (!maps[targetIndex] || comparePaths(loc.fileName, maps[targetIndex].sourcePath, sourceRoot) !== 0) {
|
||||
return loc;
|
||||
}
|
||||
return { fileName: toPath(map.file, sourceRoot, host.getCanonicalFileName), position: maps[targetIndex].emittedPosition }; // Closest pos
|
||||
return { fileName: toPath(map.file!, sourceRoot, host.getCanonicalFileName), position: maps[targetIndex].emittedPosition }; // Closest pos
|
||||
}
|
||||
|
||||
function getOriginalPosition(loc: SourceMappableLocation): SourceMappableLocation {
|
||||
@@ -68,7 +68,7 @@ namespace ts.sourcemaps {
|
||||
|
||||
function getSourceFileLike(fileName: string, location: string): SourceFileLike | undefined {
|
||||
// Lookup file in program, if provided
|
||||
const file: SourceFileLike = program && program.getSourceFile(fileName);
|
||||
const file = program && program.getSourceFile(fileName);
|
||||
if (!file) {
|
||||
// Otherwise check the cache (which may hit disk)
|
||||
const path = toPath(fileName, location, host.getCanonicalFileName);
|
||||
@@ -133,7 +133,7 @@ namespace ts.sourcemaps {
|
||||
function processPosition(position: RawSourceMapPosition): ProcessedSourceMapPosition {
|
||||
const sourcePath = map.sources[position.sourceIndex];
|
||||
return {
|
||||
emittedPosition: getPositionOfLineAndCharacterUsingName(map.file, currentDirectory, position.emittedLine, position.emittedColumn),
|
||||
emittedPosition: getPositionOfLineAndCharacterUsingName(map.file!, currentDirectory, position.emittedLine, position.emittedColumn),
|
||||
sourcePosition: getPositionOfLineAndCharacterUsingName(sourcePath, sourceRoot, position.sourceLine, position.sourceColumn),
|
||||
sourcePath,
|
||||
// TODO: Consider using `name` field to remap the expected identifier to scan for renames to handle another tool renaming oout output
|
||||
@@ -164,7 +164,7 @@ namespace ts.sourcemaps {
|
||||
currentSourceLine: number;
|
||||
currentSourceColumn: number;
|
||||
currentSourceIndex: number;
|
||||
currentNameIndex: number;
|
||||
currentNameIndex: number | undefined;
|
||||
encodedText: string;
|
||||
sourceMapNamesLength?: number;
|
||||
error?: string;
|
||||
@@ -282,14 +282,14 @@ namespace ts.sourcemaps {
|
||||
return condition;
|
||||
}
|
||||
|
||||
function base64VLQFormatDecode() {
|
||||
function base64VLQFormatDecode(): number {
|
||||
let moreDigits = true;
|
||||
let shiftCount = 0;
|
||||
let value = 0;
|
||||
|
||||
for (; moreDigits; state.decodingIndex++) {
|
||||
if (createErrorIfCondition(state.decodingIndex >= state.encodedText.length, "Error in decoding base64VLQFormatDecode, past the mapping string")) {
|
||||
return;
|
||||
return undefined!; // TODO: GH#18217
|
||||
}
|
||||
|
||||
// 6 digit number
|
||||
|
||||
@@ -18,8 +18,7 @@ namespace ts {
|
||||
case SyntaxKind.FunctionDeclaration:
|
||||
case SyntaxKind.FunctionExpression:
|
||||
if (isJsFile) {
|
||||
const symbol = node.symbol;
|
||||
if (symbol.members && (symbol.members.size > 0)) {
|
||||
if (node.symbol.members && (node.symbol.members.size > 0)) {
|
||||
diags.push(createDiagnosticForNode(isVariableDeclaration(node.parent) ? node.parent.name : node, Diagnostics.This_constructor_function_may_be_converted_to_a_class_declaration));
|
||||
}
|
||||
}
|
||||
@@ -70,7 +69,7 @@ namespace ts {
|
||||
switch (statement.kind) {
|
||||
case SyntaxKind.VariableStatement:
|
||||
return (statement as VariableStatement).declarationList.declarations.some(decl =>
|
||||
isRequireCall(propertyAccessLeftHandSide(decl.initializer), /*checkArgumentIsStringLiteralLike*/ true));
|
||||
isRequireCall(propertyAccessLeftHandSide(decl.initializer!), /*checkArgumentIsStringLiteralLike*/ true)); // TODO: GH#18217
|
||||
case SyntaxKind.ExpressionStatement: {
|
||||
const { expression } = statement as ExpressionStatement;
|
||||
if (!isBinaryExpression(expression)) return isRequireCall(expression, /*checkArgumentIsStringLiteralLike*/ true);
|
||||
@@ -91,7 +90,7 @@ namespace ts {
|
||||
switch (node.kind) {
|
||||
case SyntaxKind.ImportDeclaration:
|
||||
const { importClause, moduleSpecifier } = node;
|
||||
return importClause && !importClause.name && importClause.namedBindings.kind === SyntaxKind.NamespaceImport && isStringLiteral(moduleSpecifier)
|
||||
return importClause && !importClause.name && importClause.namedBindings && importClause.namedBindings.kind === SyntaxKind.NamespaceImport && isStringLiteral(moduleSpecifier)
|
||||
? importClause.namedBindings.name
|
||||
: undefined;
|
||||
case SyntaxKind.ImportEqualsDeclaration:
|
||||
|
||||
@@ -117,24 +117,24 @@ namespace ts.SymbolDisplay {
|
||||
displayParts: SymbolDisplayPart[];
|
||||
documentation: SymbolDisplayPart[];
|
||||
symbolKind: ScriptElementKind;
|
||||
tags: JSDocTagInfo[];
|
||||
tags: JSDocTagInfo[] | undefined;
|
||||
}
|
||||
|
||||
// TODO(drosen): Currently completion entry details passes the SemanticMeaning.All instead of using semanticMeaning of location
|
||||
export function getSymbolDisplayPartsDocumentationAndSymbolKind(typeChecker: TypeChecker, symbol: Symbol, sourceFile: SourceFile, enclosingDeclaration: Node,
|
||||
export function getSymbolDisplayPartsDocumentationAndSymbolKind(typeChecker: TypeChecker, symbol: Symbol, sourceFile: SourceFile, enclosingDeclaration: Node | undefined,
|
||||
location: Node, semanticMeaning = getMeaningFromLocation(location), alias?: Symbol): SymbolDisplayPartsDocumentationAndSymbolKind {
|
||||
|
||||
const displayParts: SymbolDisplayPart[] = [];
|
||||
let documentation: SymbolDisplayPart[];
|
||||
let tags: JSDocTagInfo[];
|
||||
let documentation: SymbolDisplayPart[] | undefined;
|
||||
let tags: JSDocTagInfo[] | undefined;
|
||||
const symbolFlags = getCombinedLocalAndExportSymbolFlags(symbol);
|
||||
let symbolKind = getSymbolKindOfConstructorPropertyMethodAccessorFunctionOrVar(typeChecker, symbol, location);
|
||||
let hasAddedSymbolInfo: boolean;
|
||||
let hasAddedSymbolInfo = false;
|
||||
const isThisExpression = location.kind === SyntaxKind.ThisKeyword && isExpression(location);
|
||||
let type: Type;
|
||||
let type: Type | undefined;
|
||||
let printer: Printer;
|
||||
let documentationFromAlias: SymbolDisplayPart[];
|
||||
let tagsFromAlias: JSDocTagInfo[];
|
||||
let documentationFromAlias: SymbolDisplayPart[] | undefined;
|
||||
let tagsFromAlias: JSDocTagInfo[] | undefined;
|
||||
|
||||
// Class at constructor site need to be shown as constructor apart from property,method, vars
|
||||
if (symbolKind !== ScriptElementKind.unknown || symbolFlags & SymbolFlags.Class || symbolFlags & SymbolFlags.Alias) {
|
||||
@@ -143,7 +143,7 @@ namespace ts.SymbolDisplay {
|
||||
symbolKind = ScriptElementKind.memberVariableElement;
|
||||
}
|
||||
|
||||
let signature: Signature;
|
||||
let signature: Signature | undefined;
|
||||
type = isThisExpression ? typeChecker.getTypeAtLocation(location) : typeChecker.getTypeOfSymbolAtLocation(symbol.exportSymbol || symbol, location);
|
||||
|
||||
if (location.parent && location.parent.kind === SyntaxKind.PropertyAccessExpression) {
|
||||
@@ -155,7 +155,7 @@ namespace ts.SymbolDisplay {
|
||||
}
|
||||
|
||||
// try get the call/construct signature from the type if it matches
|
||||
let callExpressionLike: CallExpression | NewExpression | JsxOpeningLikeElement;
|
||||
let callExpressionLike: CallExpression | NewExpression | JsxOpeningLikeElement | undefined;
|
||||
if (isCallOrNewExpression(location)) {
|
||||
callExpressionLike = location;
|
||||
}
|
||||
@@ -168,11 +168,11 @@ namespace ts.SymbolDisplay {
|
||||
|
||||
if (callExpressionLike) {
|
||||
const candidateSignatures: Signature[] = [];
|
||||
signature = typeChecker.getResolvedSignature(callExpressionLike, candidateSignatures);
|
||||
signature = typeChecker.getResolvedSignature(callExpressionLike, candidateSignatures)!; // TODO: GH#18217
|
||||
|
||||
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
|
||||
@@ -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;
|
||||
@@ -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) {
|
||||
@@ -238,9 +238,9 @@ 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);
|
||||
signature = typeChecker.getSignatureFromDeclaration(functionDeclaration)!; // TODO: GH#18217
|
||||
}
|
||||
else {
|
||||
signature = allSignatures[0];
|
||||
@@ -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);
|
||||
@@ -330,13 +330,13 @@ namespace ts.SymbolDisplay {
|
||||
else {
|
||||
// Method/function type parameter
|
||||
const decl = getDeclarationOfKind(symbol, SyntaxKind.TypeParameter);
|
||||
Debug.assert(decl !== undefined);
|
||||
if (decl === undefined) return Debug.fail();
|
||||
const declaration = decl.parent;
|
||||
|
||||
if (declaration) {
|
||||
if (isFunctionLikeKind(declaration.kind)) {
|
||||
addInPrefix();
|
||||
const signature = typeChecker.getSignatureFromDeclaration(<SignatureDeclaration>declaration);
|
||||
const signature = typeChecker.getSignatureFromDeclaration(<SignatureDeclaration>declaration)!; // TODO: GH#18217
|
||||
if (declaration.kind === SyntaxKind.ConstructSignature) {
|
||||
displayParts.push(keywordPart(SyntaxKind.NewKeyword));
|
||||
displayParts.push(spacePart());
|
||||
@@ -468,7 +468,7 @@ namespace ts.SymbolDisplay {
|
||||
// If the type is type parameter, format it specially
|
||||
if (type.symbol && type.symbol.flags & SymbolFlags.TypeParameter) {
|
||||
const typeParameterParts = mapToDisplayParts(writer => {
|
||||
const param = typeChecker.typeParameterToDeclaration(type as TypeParameter, enclosingDeclaration);
|
||||
const param = typeChecker.typeParameterToDeclaration(type as TypeParameter, enclosingDeclaration)!;
|
||||
getPrinter().writeNode(EmitHint.Unspecified, param, getSourceFileOfNode(getParseTreeNode(enclosingDeclaration)), writer);
|
||||
});
|
||||
addRange(displayParts, typeParameterParts);
|
||||
@@ -526,11 +526,11 @@ namespace ts.SymbolDisplay {
|
||||
if (documentation.length === 0 && documentationFromAlias) {
|
||||
documentation = documentationFromAlias;
|
||||
}
|
||||
if (tags.length === 0 && tagsFromAlias) {
|
||||
if (tags!.length === 0 && tagsFromAlias) {
|
||||
tags = tagsFromAlias;
|
||||
}
|
||||
|
||||
return { displayParts, documentation, symbolKind, tags };
|
||||
return { displayParts, documentation, symbolKind, tags: tags! };
|
||||
|
||||
function getPrinter() {
|
||||
if (!printer) {
|
||||
@@ -600,7 +600,7 @@ namespace ts.SymbolDisplay {
|
||||
}
|
||||
}
|
||||
|
||||
function addSignatureDisplayParts(signature: Signature, allSignatures: Signature[], flags?: TypeFormatFlags) {
|
||||
function addSignatureDisplayParts(signature: Signature, allSignatures: Signature[], flags = TypeFormatFlags.None) {
|
||||
addRange(displayParts, signatureToDisplayParts(typeChecker, signature, enclosingDeclaration, flags | TypeFormatFlags.WriteTypeArgumentsOfSignature));
|
||||
if (allSignatures.length > 1) {
|
||||
displayParts.push(spacePart());
|
||||
@@ -615,7 +615,7 @@ namespace ts.SymbolDisplay {
|
||||
tags = signature.getJsDocTags();
|
||||
}
|
||||
|
||||
function writeTypeParametersOfSymbol(symbol: Symbol, enclosingDeclaration: Node) {
|
||||
function writeTypeParametersOfSymbol(symbol: Symbol, enclosingDeclaration: Node | undefined) {
|
||||
const typeParameterParts = mapToDisplayParts(writer => {
|
||||
const params = typeChecker.symbolToTypeParameterDeclarations(symbol, enclosingDeclaration);
|
||||
getPrinter().writeList(ListFormat.TypeParameters, params, getSourceFileOfNode(getParseTreeNode(enclosingDeclaration)), writer);
|
||||
|
||||
+23
-23
@@ -190,8 +190,8 @@ namespace ts.textChanges {
|
||||
/**
|
||||
* Checks if 'candidate' argument is a legal separator in the list that contains 'node' as an element
|
||||
*/
|
||||
function isSeparator(node: Node, candidate: Node): candidate is Token<SyntaxKind.CommaToken | SyntaxKind.SemicolonToken> {
|
||||
return candidate && node.parent && (candidate.kind === SyntaxKind.CommaToken || (candidate.kind === SyntaxKind.SemicolonToken && node.parent.kind === SyntaxKind.ObjectLiteralExpression));
|
||||
function isSeparator(node: Node, candidate: Node | undefined): candidate is Token<SyntaxKind.CommaToken | SyntaxKind.SemicolonToken> {
|
||||
return !!candidate && !!node.parent && (candidate.kind === SyntaxKind.CommaToken || (candidate.kind === SyntaxKind.SemicolonToken && node.parent.kind === SyntaxKind.ObjectLiteralExpression));
|
||||
}
|
||||
|
||||
function spaces(count: number) {
|
||||
@@ -359,7 +359,7 @@ namespace ts.textChanges {
|
||||
|
||||
/** Prefer this over replacing a node with another that has a type annotation, as it avoids reformatting the other parts of the node. */
|
||||
public tryInsertTypeAnnotation(sourceFile: SourceFile, node: TypeAnnotatable, type: TypeNode): void {
|
||||
let endNode: Node;
|
||||
let endNode: Node | undefined;
|
||||
if (isFunctionLike(node)) {
|
||||
endNode = findChildOfKind(node, SyntaxKind.CloseParenToken, sourceFile);
|
||||
if (!endNode) {
|
||||
@@ -395,9 +395,9 @@ namespace ts.textChanges {
|
||||
}
|
||||
|
||||
public insertNodeAtConstructorStart(sourceFile: SourceFile, ctr: ConstructorDeclaration, newStatement: Statement): void {
|
||||
const firstStatement = firstOrUndefined(ctr.body.statements);
|
||||
if (!firstStatement || !ctr.body.multiLine) {
|
||||
this.replaceConstructorBody(sourceFile, ctr, [newStatement, ...ctr.body.statements]);
|
||||
const firstStatement = firstOrUndefined(ctr.body!.statements);
|
||||
if (!firstStatement || !ctr.body!.multiLine) {
|
||||
this.replaceConstructorBody(sourceFile, ctr, [newStatement, ...ctr.body!.statements]);
|
||||
}
|
||||
else {
|
||||
this.insertNodeBefore(sourceFile, firstStatement, newStatement);
|
||||
@@ -405,9 +405,9 @@ namespace ts.textChanges {
|
||||
}
|
||||
|
||||
public insertNodeAtConstructorEnd(sourceFile: SourceFile, ctr: ConstructorDeclaration, newStatement: Statement): void {
|
||||
const lastStatement = lastOrUndefined(ctr.body.statements);
|
||||
if (!lastStatement || !ctr.body.multiLine) {
|
||||
this.replaceConstructorBody(sourceFile, ctr, [...ctr.body.statements, newStatement]);
|
||||
const lastStatement = lastOrUndefined(ctr.body!.statements);
|
||||
if (!lastStatement || !ctr.body!.multiLine) {
|
||||
this.replaceConstructorBody(sourceFile, ctr, [...ctr.body!.statements, newStatement]);
|
||||
}
|
||||
else {
|
||||
this.insertNodeAfter(sourceFile, lastStatement, newStatement);
|
||||
@@ -415,13 +415,13 @@ namespace ts.textChanges {
|
||||
}
|
||||
|
||||
private replaceConstructorBody(sourceFile: SourceFile, ctr: ConstructorDeclaration, statements: ReadonlyArray<Statement>): void {
|
||||
this.replaceNode(sourceFile, ctr.body, createBlock(statements, /*multiLine*/ true));
|
||||
this.replaceNode(sourceFile, ctr.body!, createBlock(statements, /*multiLine*/ true));
|
||||
}
|
||||
|
||||
public insertNodeAtEndOfScope(sourceFile: SourceFile, scope: Node, newNode: Node): void {
|
||||
const pos = getAdjustedStartPosition(sourceFile, scope.getLastToken(), {}, Position.Start);
|
||||
const pos = getAdjustedStartPosition(sourceFile, scope.getLastToken()!, {}, Position.Start);
|
||||
this.replaceRange(sourceFile, { pos, end: pos }, newNode, {
|
||||
prefix: isLineBreak(sourceFile.text.charCodeAt(scope.getLastToken().pos)) ? this.newLineCharacter : this.newLineCharacter + this.newLineCharacter,
|
||||
prefix: isLineBreak(sourceFile.text.charCodeAt(scope.getLastToken()!.pos)) ? this.newLineCharacter : this.newLineCharacter + this.newLineCharacter,
|
||||
suffix: this.newLineCharacter
|
||||
});
|
||||
}
|
||||
@@ -429,7 +429,7 @@ namespace ts.textChanges {
|
||||
public insertNodeAtClassStart(sourceFile: SourceFile, cls: ClassLikeDeclaration, newElement: ClassElement): void {
|
||||
const clsStart = cls.getStart(sourceFile);
|
||||
const indentation = formatting.SmartIndenter.findFirstNonWhitespaceColumn(getLineStartPositionForPosition(clsStart, sourceFile), clsStart, sourceFile, this.formatContext.options)
|
||||
+ this.formatContext.options.indentSize;
|
||||
+ this.formatContext.options.indentSize!;
|
||||
this.insertNodeAt(sourceFile, cls.members.pos, newElement, { indentation, ...this.getInsertNodeAtClassStartPrefixSuffix(sourceFile, cls) });
|
||||
}
|
||||
|
||||
@@ -575,7 +575,7 @@ namespace ts.textChanges {
|
||||
const lineAndCharOfNextElement = getLineAndCharacterOfPosition(sourceFile, skipWhitespacesAndLineBreaks(sourceFile.text, containingList[index + 1].getFullStart()));
|
||||
// find line and character of the token that precedes next element (usually it is separator)
|
||||
const lineAndCharOfNextToken = getLineAndCharacterOfPosition(sourceFile, nextToken.end);
|
||||
let prefix: string;
|
||||
let prefix: string | undefined;
|
||||
let startPos: number;
|
||||
if (lineAndCharOfNextToken.line === lineAndCharOfNextElement.line) {
|
||||
// next element is located on the same line with separator:
|
||||
@@ -608,7 +608,7 @@ namespace ts.textChanges {
|
||||
const afterStart = after.getStart(sourceFile);
|
||||
const afterStartLinePosition = getLineStartPositionForPosition(afterStart, sourceFile);
|
||||
|
||||
let separator: SyntaxKind.CommaToken | SyntaxKind.SemicolonToken;
|
||||
let separator: SyntaxKind.CommaToken | SyntaxKind.SemicolonToken | undefined;
|
||||
let multilineList = false;
|
||||
|
||||
// insert element after the last element in the list that has more than one item
|
||||
@@ -666,7 +666,7 @@ namespace ts.textChanges {
|
||||
private finishTrailingCommaAfterDeletingNodesInList() {
|
||||
this.deletedNodesInLists.forEach(node => {
|
||||
const sourceFile = node.getSourceFile();
|
||||
const list = formatting.SmartIndenter.getContainingList(node, sourceFile);
|
||||
const list = formatting.SmartIndenter.getContainingList(node, sourceFile)!;
|
||||
if (node !== last(list)) return;
|
||||
|
||||
const lastNonDeletedIndex = findLastIndex(list, n => !this.deletedNodesInLists.has(n), list.length - 2);
|
||||
@@ -703,13 +703,13 @@ namespace ts.textChanges {
|
||||
}
|
||||
|
||||
function getClassBraceEnds(cls: ClassLikeDeclaration, sourceFile: SourceFile): [number, number] {
|
||||
return [findChildOfKind(cls, SyntaxKind.OpenBraceToken, sourceFile).end, findChildOfKind(cls, SyntaxKind.CloseBraceToken, sourceFile).end];
|
||||
return [findChildOfKind(cls, SyntaxKind.OpenBraceToken, sourceFile)!.end, findChildOfKind(cls, SyntaxKind.CloseBraceToken, sourceFile)!.end];
|
||||
}
|
||||
|
||||
export type ValidateNonFormattedText = (node: Node, text: string) => void;
|
||||
|
||||
namespace changesToText {
|
||||
export function getTextChangesFromChanges(changes: ReadonlyArray<Change>, newLineCharacter: string, formatContext: formatting.FormatContext, validate: ValidateNonFormattedText): FileTextChanges[] {
|
||||
export function getTextChangesFromChanges(changes: ReadonlyArray<Change>, newLineCharacter: string, formatContext: formatting.FormatContext, validate: ValidateNonFormattedText | undefined): FileTextChanges[] {
|
||||
return group(changes, c => c.sourceFile.path).map(changesInFile => {
|
||||
const sourceFile = changesInFile[0].sourceFile;
|
||||
// order changes by start position
|
||||
@@ -731,7 +731,7 @@ namespace ts.textChanges {
|
||||
return { fileName, textChanges: [createTextChange(createTextSpan(0, 0), text)], isNewFile: true };
|
||||
}
|
||||
|
||||
function computeNewText(change: Change, sourceFile: SourceFile, newLineCharacter: string, formatContext: formatting.FormatContext, validate: ValidateNonFormattedText): string {
|
||||
function computeNewText(change: Change, sourceFile: SourceFile, newLineCharacter: string, formatContext: formatting.FormatContext, validate: ValidateNonFormattedText | undefined): string {
|
||||
if (change.kind === ChangeKind.Remove) {
|
||||
return "";
|
||||
}
|
||||
@@ -742,7 +742,7 @@ namespace ts.textChanges {
|
||||
const { options = {}, range: { pos } } = change;
|
||||
const format = (n: Node) => getFormattedTextOfNode(n, sourceFile, pos, options, newLineCharacter, formatContext, validate);
|
||||
const text = change.kind === ChangeKind.ReplaceWithMultipleNodes
|
||||
? change.nodes.map(n => removeSuffix(format(n), newLineCharacter)).join(change.options.joiner || newLineCharacter)
|
||||
? change.nodes.map(n => removeSuffix(format(n), newLineCharacter)).join(change.options!.joiner || newLineCharacter) // TODO: GH#18217
|
||||
: format(change.node);
|
||||
// strip initial indentation (spaces or tabs) if text will be inserted in the middle of the line
|
||||
const noIndent = (options.preserveLeadingWhitespace || options.indentation !== undefined || getLineStartPositionForPosition(pos, sourceFile) === pos) ? text : text.replace(/^\s+/, "");
|
||||
@@ -750,7 +750,7 @@ namespace ts.textChanges {
|
||||
}
|
||||
|
||||
/** Note: this may mutate `nodeIn`. */
|
||||
function getFormattedTextOfNode(nodeIn: Node, sourceFile: SourceFile, pos: number, { indentation, prefix, delta }: InsertNodeOptions, newLineCharacter: string, formatContext: formatting.FormatContext, validate: ValidateNonFormattedText): string {
|
||||
function getFormattedTextOfNode(nodeIn: Node, sourceFile: SourceFile, pos: number, { indentation, prefix, delta }: InsertNodeOptions, newLineCharacter: string, formatContext: formatting.FormatContext, validate: ValidateNonFormattedText | undefined): string {
|
||||
const { node, text } = getNonformattedText(nodeIn, sourceFile, newLineCharacter);
|
||||
if (validate) validate(node, text);
|
||||
const { options: formatOptions } = formatContext;
|
||||
@@ -789,7 +789,7 @@ namespace ts.textChanges {
|
||||
}
|
||||
|
||||
function assignPositionsToNode(node: Node): Node {
|
||||
const visited = visitEachChild(node, assignPositionsToNode, nullTransformationContext, assignPositionsToNodeArray, assignPositionsToNode);
|
||||
const visited = visitEachChild(node, assignPositionsToNode, nullTransformationContext, assignPositionsToNodeArray, assignPositionsToNode)!; // TODO: GH#18217
|
||||
// create proxy node for non synthesized nodes
|
||||
const newNode = nodeIsSynthesized(visited) ? visited : Object.create(visited) as Node;
|
||||
newNode.pos = getPos(node);
|
||||
@@ -991,7 +991,7 @@ namespace ts.textChanges {
|
||||
}
|
||||
|
||||
function needSemicolonBetween(a: Node, b: Node): boolean {
|
||||
return (isPropertySignature(a) || isPropertyDeclaration(a)) && isClassOrTypeElement(b) && b.name.kind === SyntaxKind.ComputedPropertyName
|
||||
return (isPropertySignature(a) || isPropertyDeclaration(a)) && isClassOrTypeElement(b) && b.name!.kind === SyntaxKind.ComputedPropertyName
|
||||
|| isStatementButNotDeclaration(a) && isStatementButNotDeclaration(b); // TODO: only if b would start with a `(` or `[`
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ namespace ts {
|
||||
*/
|
||||
export function transform<T extends Node>(source: T | T[], transformers: TransformerFactory<T>[], compilerOptions?: CompilerOptions) {
|
||||
const diagnostics: DiagnosticWithLocation[] = [];
|
||||
compilerOptions = fixupCompilerOptions(compilerOptions, diagnostics);
|
||||
compilerOptions = fixupCompilerOptions(compilerOptions!, diagnostics); // TODO: GH#18217
|
||||
const nodes = isArray(source) ? source : [source];
|
||||
const result = transformNodes(/*resolver*/ undefined, /*emitHost*/ undefined, compilerOptions, nodes, transformers, /*allowDtsFiles*/ true);
|
||||
result.diagnostics = concatenate(result.diagnostics, diagnostics);
|
||||
|
||||
@@ -58,7 +58,7 @@ namespace ts {
|
||||
|
||||
// if jsx is specified then treat file as .tsx
|
||||
const inputFileName = transpileOptions.fileName || (options.jsx ? "module.tsx" : "module.ts");
|
||||
const sourceFile = createSourceFile(inputFileName, input, options.target);
|
||||
const sourceFile = createSourceFile(inputFileName, input, options.target!); // TODO: GH#18217
|
||||
if (transpileOptions.moduleName) {
|
||||
sourceFile.moduleName = transpileOptions.moduleName;
|
||||
}
|
||||
@@ -70,8 +70,8 @@ namespace ts {
|
||||
const newLine = getNewLineCharacter(options);
|
||||
|
||||
// Output
|
||||
let outputText: string;
|
||||
let sourceMapText: string;
|
||||
let outputText: string | undefined;
|
||||
let sourceMapText: string | undefined;
|
||||
|
||||
// Create a compilerHost object to allow the compiler to read and write files
|
||||
const compilerHost: CompilerHost = {
|
||||
@@ -106,7 +106,7 @@ namespace ts {
|
||||
// Emit
|
||||
program.emit(/*targetSourceFile*/ undefined, /*writeFile*/ undefined, /*cancellationToken*/ undefined, /*emitOnlyDtsFiles*/ undefined, transpileOptions.transformers);
|
||||
|
||||
Debug.assert(outputText !== undefined, "Output generation failed");
|
||||
if (outputText === undefined) return Debug.fail("Output generation failed");
|
||||
|
||||
return { outputText, diagnostics, sourceMapText };
|
||||
}
|
||||
|
||||
+38
-37
@@ -18,8 +18,8 @@ namespace ts {
|
||||
getLeadingTriviaWidth(sourceFile?: SourceFile): number;
|
||||
getFullText(sourceFile?: SourceFile): string;
|
||||
getText(sourceFile?: SourceFile): string;
|
||||
getFirstToken(sourceFile?: SourceFile): Node;
|
||||
getLastToken(sourceFile?: SourceFile): Node;
|
||||
getFirstToken(sourceFile?: SourceFile): Node | undefined;
|
||||
getLastToken(sourceFile?: SourceFile): Node | undefined;
|
||||
// See ts.forEachChild for documentation.
|
||||
forEachChild<T>(cbNode: (node: Node) => T | undefined, cbNodeArray?: (nodes: NodeArray<Node>) => T | undefined): T | undefined;
|
||||
}
|
||||
@@ -75,8 +75,8 @@ namespace ts {
|
||||
|
||||
export interface SourceFile {
|
||||
/* @internal */ version: string;
|
||||
/* @internal */ scriptSnapshot: IScriptSnapshot;
|
||||
/* @internal */ nameTable: UnderscoreEscapedMap<number>;
|
||||
/* @internal */ scriptSnapshot: IScriptSnapshot | undefined;
|
||||
/* @internal */ nameTable: UnderscoreEscapedMap<number> | undefined;
|
||||
|
||||
/* @internal */ getNamedDeclarations(): Map<Declaration[]>;
|
||||
|
||||
@@ -140,7 +140,7 @@ namespace ts {
|
||||
return this.text.length;
|
||||
}
|
||||
|
||||
public getChangeRange(): TextChangeRange {
|
||||
public getChangeRange(): TextChangeRange | undefined {
|
||||
// Text-based snapshots do not support incremental parsing. Return undefined
|
||||
// to signal that to the caller.
|
||||
return undefined;
|
||||
@@ -155,7 +155,7 @@ namespace ts {
|
||||
referencedFiles: FileReference[];
|
||||
typeReferenceDirectives: FileReference[];
|
||||
importedFiles: FileReference[];
|
||||
ambientExternalModules: string[];
|
||||
ambientExternalModules?: string[];
|
||||
isLibFile: boolean;
|
||||
}
|
||||
|
||||
@@ -211,7 +211,7 @@ namespace ts {
|
||||
* If this is implemented, `getResolvedModuleWithFailedLookupLocationsFromCache` should be too.
|
||||
*/
|
||||
resolveModuleNames?(moduleNames: string[], containingFile: string, reusedNames?: string[]): ResolvedModule[];
|
||||
getResolvedModuleWithFailedLookupLocationsFromCache?(modulename: string, containingFile: string): ResolvedModuleWithFailedLookupLocations;
|
||||
getResolvedModuleWithFailedLookupLocationsFromCache?(modulename: string, containingFile: string): ResolvedModuleWithFailedLookupLocations | undefined;
|
||||
resolveTypeReferenceDirectives?(typeDirectiveNames: string[], containingFile: string): ResolvedTypeReferenceDirective[];
|
||||
/* @internal */ hasInvalidatedResolution?: HasInvalidatedResolution;
|
||||
/* @internal */ hasChangedAutomaticTypeDirectiveNames?: boolean;
|
||||
@@ -272,7 +272,7 @@ namespace ts {
|
||||
getEncodedSyntacticClassifications(fileName: string, span: TextSpan): Classifications;
|
||||
getEncodedSemanticClassifications(fileName: string, span: TextSpan): Classifications;
|
||||
|
||||
getCompletionsAtPosition(fileName: string, position: number, options: GetCompletionsAtPositionOptions | undefined): CompletionInfo;
|
||||
getCompletionsAtPosition(fileName: string, position: number, options: GetCompletionsAtPositionOptions | undefined): CompletionInfo | undefined;
|
||||
// "options" and "source" are optional only for backwards-compatibility
|
||||
getCompletionEntryDetails(
|
||||
fileName: string,
|
||||
@@ -281,31 +281,31 @@ namespace ts {
|
||||
formatOptions: FormatCodeOptions | FormatCodeSettings | undefined,
|
||||
source: string | undefined,
|
||||
preferences: UserPreferences | undefined,
|
||||
): CompletionEntryDetails;
|
||||
getCompletionEntrySymbol(fileName: string, position: number, name: string, source: string | undefined): Symbol;
|
||||
): CompletionEntryDetails | undefined;
|
||||
getCompletionEntrySymbol(fileName: string, position: number, name: string, source: string | undefined): Symbol | undefined;
|
||||
|
||||
getQuickInfoAtPosition(fileName: string, position: number): QuickInfo;
|
||||
getQuickInfoAtPosition(fileName: string, position: number): QuickInfo | undefined;
|
||||
|
||||
getNameOrDottedNameSpan(fileName: string, startPos: number, endPos: number): TextSpan;
|
||||
getNameOrDottedNameSpan(fileName: string, startPos: number, endPos: number): TextSpan | undefined;
|
||||
|
||||
getBreakpointStatementAtPosition(fileName: string, position: number): TextSpan;
|
||||
getBreakpointStatementAtPosition(fileName: string, position: number): TextSpan | undefined;
|
||||
|
||||
getSignatureHelpItems(fileName: string, position: number): SignatureHelpItems;
|
||||
getSignatureHelpItems(fileName: string, position: number): SignatureHelpItems | undefined;
|
||||
|
||||
getRenameInfo(fileName: string, position: number): RenameInfo;
|
||||
findRenameLocations(fileName: string, position: number, findInStrings: boolean, findInComments: boolean): RenameLocation[];
|
||||
findRenameLocations(fileName: string, position: number, findInStrings: boolean, findInComments: boolean): RenameLocation[] | undefined;
|
||||
|
||||
getDefinitionAtPosition(fileName: string, position: number): DefinitionInfo[];
|
||||
getDefinitionAndBoundSpan(fileName: string, position: number): DefinitionInfoAndBoundSpan;
|
||||
getTypeDefinitionAtPosition(fileName: string, position: number): DefinitionInfo[];
|
||||
getImplementationAtPosition(fileName: string, position: number): ImplementationLocation[];
|
||||
getDefinitionAtPosition(fileName: string, position: number): DefinitionInfo[] | undefined;
|
||||
getDefinitionAndBoundSpan(fileName: string, position: number): DefinitionInfoAndBoundSpan | undefined;
|
||||
getTypeDefinitionAtPosition(fileName: string, position: number): DefinitionInfo[] | undefined;
|
||||
getImplementationAtPosition(fileName: string, position: number): ImplementationLocation[] | undefined;
|
||||
|
||||
getReferencesAtPosition(fileName: string, position: number): ReferenceEntry[];
|
||||
findReferences(fileName: string, position: number): ReferencedSymbol[];
|
||||
getDocumentHighlights(fileName: string, position: number, filesToSearch: string[]): DocumentHighlights[];
|
||||
getReferencesAtPosition(fileName: string, position: number): ReferenceEntry[] | undefined;
|
||||
findReferences(fileName: string, position: number): ReferencedSymbol[] | undefined;
|
||||
getDocumentHighlights(fileName: string, position: number, filesToSearch: string[]): DocumentHighlights[] | undefined;
|
||||
|
||||
/** @deprecated */
|
||||
getOccurrencesAtPosition(fileName: string, position: number): ReferenceEntry[];
|
||||
getOccurrencesAtPosition(fileName: string, position: number): ReferenceEntry[] | undefined;
|
||||
|
||||
getNavigateToItems(searchValue: string, maxResultCount?: number, fileName?: string, excludeDtsFiles?: boolean): NavigateToItem[];
|
||||
getNavigationBarItems(fileName: string): NavigationBarItem[];
|
||||
@@ -320,11 +320,11 @@ namespace ts {
|
||||
getFormattingEditsForDocument(fileName: string, options: FormatCodeOptions | FormatCodeSettings): TextChange[];
|
||||
getFormattingEditsAfterKeystroke(fileName: string, position: number, key: string, options: FormatCodeOptions | FormatCodeSettings): TextChange[];
|
||||
|
||||
getDocCommentTemplateAtPosition(fileName: string, position: number): TextInsertion;
|
||||
getDocCommentTemplateAtPosition(fileName: string, position: number): TextInsertion | undefined;
|
||||
|
||||
isValidBraceCompletionAtPosition(fileName: string, position: number, openingBrace: number): boolean;
|
||||
|
||||
getSpanOfEnclosingComment(fileName: string, position: number, onlyMultiLine: boolean): TextSpan;
|
||||
getSpanOfEnclosingComment(fileName: string, position: number, onlyMultiLine: boolean): TextSpan | undefined;
|
||||
|
||||
toLineColumnOffset?(fileName: string, position: number): LineAndCharacter;
|
||||
|
||||
@@ -346,7 +346,7 @@ namespace ts {
|
||||
|
||||
getEmitOutput(fileName: string, emitOnlyDtsFiles?: boolean): EmitOutput;
|
||||
|
||||
getProgram(): Program;
|
||||
getProgram(): Program | undefined;
|
||||
|
||||
/* @internal */ getNonBoundSourceFile(fileName: string): SourceFile;
|
||||
|
||||
@@ -471,7 +471,7 @@ namespace ts {
|
||||
|
||||
export interface CombinedCodeActions {
|
||||
changes: ReadonlyArray<FileTextChanges>;
|
||||
commands: ReadonlyArray<CodeActionCommand> | undefined;
|
||||
commands?: ReadonlyArray<CodeActionCommand>;
|
||||
}
|
||||
|
||||
// Publicly, this type is just `{}`. Internally it is a union of all the actions we use.
|
||||
@@ -533,8 +533,8 @@ namespace ts {
|
||||
*/
|
||||
export interface RefactorEditInfo {
|
||||
edits: FileTextChanges[];
|
||||
renameFilename: string | undefined;
|
||||
renameLocation: number | undefined;
|
||||
renameFilename?: string ;
|
||||
renameLocation?: number;
|
||||
commands?: CodeActionCommand[];
|
||||
}
|
||||
|
||||
@@ -617,6 +617,7 @@ namespace ts {
|
||||
IndentStyle: IndentStyle;
|
||||
}
|
||||
|
||||
// TODO: GH#18217 These are frequently asserted as defined
|
||||
export interface EditorSettings {
|
||||
baseIndentSize?: number;
|
||||
indentSize?: number;
|
||||
@@ -674,7 +675,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
export interface DefinitionInfoAndBoundSpan {
|
||||
definitions: ReadonlyArray<DefinitionInfo>;
|
||||
definitions?: ReadonlyArray<DefinitionInfo>;
|
||||
textSpan: TextSpan;
|
||||
}
|
||||
|
||||
@@ -726,14 +727,14 @@ namespace ts {
|
||||
kind: ScriptElementKind;
|
||||
kindModifiers: string;
|
||||
textSpan: TextSpan;
|
||||
displayParts: SymbolDisplayPart[];
|
||||
documentation: SymbolDisplayPart[];
|
||||
tags: JSDocTagInfo[];
|
||||
displayParts?: SymbolDisplayPart[];
|
||||
documentation?: SymbolDisplayPart[];
|
||||
tags?: JSDocTagInfo[];
|
||||
}
|
||||
|
||||
export interface RenameInfo {
|
||||
canRename: boolean;
|
||||
localizedErrorMessage: string;
|
||||
localizedErrorMessage?: string;
|
||||
displayName: string;
|
||||
fullDisplayName: string;
|
||||
kind: ScriptElementKind;
|
||||
@@ -792,7 +793,7 @@ namespace ts {
|
||||
export interface CompletionEntry {
|
||||
name: string;
|
||||
kind: ScriptElementKind;
|
||||
kindModifiers: string; // see ScriptElementKindModifier, comma separated
|
||||
kindModifiers?: string; // see ScriptElementKindModifier, comma separated
|
||||
sortText: string;
|
||||
insertText?: string;
|
||||
/**
|
||||
@@ -811,8 +812,8 @@ namespace ts {
|
||||
kind: ScriptElementKind;
|
||||
kindModifiers: string; // see ScriptElementKindModifier, comma separated
|
||||
displayParts: SymbolDisplayPart[];
|
||||
documentation: SymbolDisplayPart[];
|
||||
tags: JSDocTagInfo[];
|
||||
documentation?: SymbolDisplayPart[];
|
||||
tags?: JSDocTagInfo[];
|
||||
codeActions?: CodeAction[];
|
||||
source?: SymbolDisplayPart[];
|
||||
}
|
||||
|
||||
+43
-36
@@ -201,16 +201,16 @@ namespace ts {
|
||||
return isCallOrNewExpressionTarget(node, SyntaxKind.NewExpression);
|
||||
}
|
||||
|
||||
function isCallOrNewExpressionTarget(node: Node, kind: SyntaxKind) {
|
||||
function isCallOrNewExpressionTarget(node: Node, kind: SyntaxKind): boolean {
|
||||
const target = climbPastPropertyAccess(node);
|
||||
return target && target.parent && target.parent.kind === kind && (<CallExpression>target.parent).expression === target;
|
||||
return !!target && !!target.parent && target.parent.kind === kind && (<CallExpression>target.parent).expression === target;
|
||||
}
|
||||
|
||||
export function climbPastPropertyAccess(node: Node) {
|
||||
return isRightSideOfPropertyAccess(node) ? node.parent : node;
|
||||
}
|
||||
|
||||
export function getTargetLabel(referenceNode: Node, labelName: string): Identifier {
|
||||
export function getTargetLabel(referenceNode: Node, labelName: string): Identifier | undefined {
|
||||
while (referenceNode) {
|
||||
if (referenceNode.kind === SyntaxKind.LabeledStatement && (<LabeledStatement>referenceNode).label.escapedText === labelName) {
|
||||
return (<LabeledStatement>referenceNode).label;
|
||||
@@ -267,6 +267,8 @@ namespace ts {
|
||||
return true;
|
||||
case SyntaxKind.LiteralType:
|
||||
return node.parent.parent.kind === SyntaxKind.IndexedAccessType;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -275,7 +277,7 @@ namespace ts {
|
||||
getExternalModuleImportEqualsDeclarationExpression(node.parent.parent) === node;
|
||||
}
|
||||
|
||||
export function getContainerNode(node: Node): Declaration {
|
||||
export function getContainerNode(node: Node): Declaration | undefined {
|
||||
if (isJSDocTypeAlias(node)) {
|
||||
// This doesn't just apply to the node immediately under the comment, but to everything in its parent's scope.
|
||||
// node.parent = the JSDoc comment, node.parent.parent = the node having the comment.
|
||||
@@ -447,8 +449,8 @@ namespace ts {
|
||||
return position < candidate.end || !isCompletedNode(candidate, sourceFile);
|
||||
}
|
||||
|
||||
function isCompletedNode(n: Node, sourceFile: SourceFile): boolean {
|
||||
if (nodeIsMissing(n)) {
|
||||
function isCompletedNode(n: Node | undefined, sourceFile: SourceFile): boolean {
|
||||
if (n === undefined || nodeIsMissing(n)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -504,7 +506,7 @@ namespace ts {
|
||||
return hasChildOfKind(n, SyntaxKind.CloseParenToken, sourceFile);
|
||||
|
||||
case SyntaxKind.ModuleDeclaration:
|
||||
return (<ModuleDeclaration>n).body && isCompletedNode((<ModuleDeclaration>n).body, sourceFile);
|
||||
return !!(<ModuleDeclaration>n).body && isCompletedNode((<ModuleDeclaration>n).body, sourceFile);
|
||||
|
||||
case SyntaxKind.IfStatement:
|
||||
if ((<IfStatement>n).elseStatement) {
|
||||
@@ -588,18 +590,18 @@ namespace ts {
|
||||
function nodeEndsWith(n: Node, expectedLastToken: SyntaxKind, sourceFile: SourceFile): boolean {
|
||||
const children = n.getChildren(sourceFile);
|
||||
if (children.length) {
|
||||
const last = lastOrUndefined(children);
|
||||
if (last.kind === expectedLastToken) {
|
||||
const lastChild = last(children);
|
||||
if (lastChild.kind === expectedLastToken) {
|
||||
return true;
|
||||
}
|
||||
else if (last.kind === SyntaxKind.SemicolonToken && children.length !== 1) {
|
||||
else if (lastChild.kind === SyntaxKind.SemicolonToken && children.length !== 1) {
|
||||
return children[children.length - 2].kind === expectedLastToken;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
export function findListItemInfo(node: Node): ListItemInfo {
|
||||
export function findListItemInfo(node: Node): ListItemInfo | undefined {
|
||||
const list = findContainingList(node);
|
||||
|
||||
// It is possible at this point for syntaxList to be undefined, either if
|
||||
@@ -655,12 +657,12 @@ namespace ts {
|
||||
}
|
||||
|
||||
/** Returns a token if position is in [start-of-leading-trivia, end) */
|
||||
export function getTokenAtPosition(sourceFile: SourceFile, position: number, includeJsDocComment: boolean, includeEndPosition?: boolean): Node {
|
||||
export function getTokenAtPosition(sourceFile: SourceFile, position: number, includeJsDocComment: boolean, includeEndPosition = false): Node {
|
||||
return getTokenAtPositionWorker(sourceFile, position, /*allowPositionInLeadingTrivia*/ true, /*includePrecedingTokenAtEndPosition*/ undefined, includeEndPosition, includeJsDocComment);
|
||||
}
|
||||
|
||||
/** Get the token whose text contains the position */
|
||||
function getTokenAtPositionWorker(sourceFile: SourceFile, position: number, allowPositionInLeadingTrivia: boolean, includePrecedingTokenAtEndPosition: (n: Node) => boolean, includeEndPosition: boolean, includeJsDocComment: boolean): Node {
|
||||
function getTokenAtPositionWorker(sourceFile: SourceFile, position: number, allowPositionInLeadingTrivia: boolean, includePrecedingTokenAtEndPosition: ((n: Node) => boolean) | undefined, includeEndPosition: boolean, includeJsDocComment: boolean): Node {
|
||||
let current: Node = sourceFile;
|
||||
outer: while (true) {
|
||||
if (isToken(current)) {
|
||||
@@ -705,7 +707,7 @@ namespace ts {
|
||||
* foo <comment> |bar -> will return foo
|
||||
*
|
||||
*/
|
||||
export function findTokenOnLeftOfPosition(file: SourceFile, position: number): Node {
|
||||
export function findTokenOnLeftOfPosition(file: SourceFile, position: number): Node | undefined {
|
||||
// Ideally, getTokenAtPosition should return a token. However, it is currently
|
||||
// broken, so we do a check to make sure the result was indeed a token.
|
||||
const tokenAtPosition = getTokenAtPosition(file, position, /*includeJsDocComment*/ false);
|
||||
@@ -716,10 +718,10 @@ namespace ts {
|
||||
return findPrecedingToken(position, file);
|
||||
}
|
||||
|
||||
export function findNextToken(previousToken: Node, parent: Node, sourceFile: SourceFile): Node {
|
||||
export function findNextToken(previousToken: Node, parent: Node, sourceFile: SourceFile): Node | undefined {
|
||||
return find(parent);
|
||||
|
||||
function find(n: Node): Node {
|
||||
function find(n: Node): Node | undefined {
|
||||
if (isToken(n) && n.pos === previousToken.end) {
|
||||
// this is token that starts at the end of previous token - return it
|
||||
return n;
|
||||
@@ -899,10 +901,11 @@ namespace ts {
|
||||
const tokenKind = token.kind;
|
||||
let remainingMatchingTokens = 0;
|
||||
while (true) {
|
||||
token = findPrecedingToken(token.getFullStart(), sourceFile);
|
||||
if (!token) {
|
||||
const preceding = findPrecedingToken(token.getFullStart(), sourceFile);
|
||||
if (!preceding) {
|
||||
return undefined;
|
||||
}
|
||||
token = preceding;
|
||||
|
||||
if (token.kind === matchingTokenKind) {
|
||||
if (remainingMatchingTokens === 0) {
|
||||
@@ -917,7 +920,8 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
export function isPossiblyTypeArgumentPosition(token: Node, sourceFile: SourceFile) {
|
||||
export function isPossiblyTypeArgumentPosition(tokenIn: Node, sourceFile: SourceFile): boolean {
|
||||
let token: Node | undefined = tokenIn;
|
||||
// This function determines if the node could be type argument position
|
||||
// Since during editing, when type argument list is not complete,
|
||||
// the tree could be of any shape depending on the tokens parsed before current node,
|
||||
@@ -929,7 +933,8 @@ namespace ts {
|
||||
case SyntaxKind.LessThanToken:
|
||||
// Found the beginning of the generic argument expression
|
||||
token = findPrecedingToken(token.getFullStart(), sourceFile);
|
||||
const tokenIsIdentifier = token && isIdentifier(token);
|
||||
if (!token) return false;
|
||||
const tokenIsIdentifier = isIdentifier(token);
|
||||
if (!remainingLessThanTokens || !tokenIsIdentifier) {
|
||||
return tokenIsIdentifier;
|
||||
}
|
||||
@@ -1052,7 +1057,7 @@ namespace ts {
|
||||
return result.length > 0 ? result.join(",") : ScriptElementKindModifier.none;
|
||||
}
|
||||
|
||||
export function getTypeArgumentOrTypeParameterList(node: Node): NodeArray<Node> {
|
||||
export function getTypeArgumentOrTypeParameterList(node: Node): NodeArray<Node> | undefined {
|
||||
if (node.kind === SyntaxKind.TypeReference || node.kind === SyntaxKind.CallExpression) {
|
||||
return (<CallExpression>node).typeArguments;
|
||||
}
|
||||
@@ -1215,7 +1220,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
export function skipConstraint(type: Type): Type {
|
||||
return type.isTypeParameter() ? type.getConstraint() : type;
|
||||
return type.isTypeParameter() ? type.getConstraint()! : type; // TODO: GH#18217
|
||||
}
|
||||
|
||||
export function getNameFromPropertyName(name: PropertyName): string | undefined {
|
||||
@@ -1229,7 +1234,7 @@ namespace ts {
|
||||
return program.getSourceFiles().some(s => !s.isDeclarationFile && !program.isSourceFileFromExternalLibrary(s) && !!s.externalModuleIndicator);
|
||||
}
|
||||
export function compilerOptionsIndicateEs6Modules(compilerOptions: CompilerOptions): boolean {
|
||||
return !!compilerOptions.module || compilerOptions.target >= ScriptTarget.ES2015 || !!compilerOptions.noEmit;
|
||||
return !!compilerOptions.module || compilerOptions.target! >= ScriptTarget.ES2015 || !!compilerOptions.noEmit;
|
||||
}
|
||||
|
||||
export function hostUsesCaseSensitiveFileNames(host: LanguageServiceHost): boolean {
|
||||
@@ -1412,15 +1417,15 @@ namespace ts {
|
||||
}
|
||||
|
||||
export function keywordPart(kind: SyntaxKind) {
|
||||
return displayPart(tokenToString(kind), SymbolDisplayPartKind.keyword);
|
||||
return displayPart(tokenToString(kind)!, SymbolDisplayPartKind.keyword);
|
||||
}
|
||||
|
||||
export function punctuationPart(kind: SyntaxKind) {
|
||||
return displayPart(tokenToString(kind), SymbolDisplayPartKind.punctuation);
|
||||
return displayPart(tokenToString(kind)!, SymbolDisplayPartKind.punctuation);
|
||||
}
|
||||
|
||||
export function operatorPart(kind: SyntaxKind) {
|
||||
return displayPart(tokenToString(kind), SymbolDisplayPartKind.operator);
|
||||
return displayPart(tokenToString(kind)!, SymbolDisplayPartKind.operator);
|
||||
}
|
||||
|
||||
export function textOrKeywordPart(text: string) {
|
||||
@@ -1459,19 +1464,19 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
export function typeToDisplayParts(typechecker: TypeChecker, type: Type, enclosingDeclaration?: Node, flags?: TypeFormatFlags): SymbolDisplayPart[] {
|
||||
export function typeToDisplayParts(typechecker: TypeChecker, type: Type, enclosingDeclaration?: Node, flags: TypeFormatFlags = TypeFormatFlags.None): SymbolDisplayPart[] {
|
||||
return mapToDisplayParts(writer => {
|
||||
typechecker.writeType(type, enclosingDeclaration, flags | TypeFormatFlags.MultilineObjectLiterals, writer);
|
||||
});
|
||||
}
|
||||
|
||||
export function symbolToDisplayParts(typeChecker: TypeChecker, symbol: Symbol, enclosingDeclaration?: Node, meaning?: SymbolFlags, flags?: SymbolFormatFlags): SymbolDisplayPart[] {
|
||||
export function symbolToDisplayParts(typeChecker: TypeChecker, symbol: Symbol, enclosingDeclaration?: Node, meaning?: SymbolFlags, flags: SymbolFormatFlags = SymbolFormatFlags.None): SymbolDisplayPart[] {
|
||||
return mapToDisplayParts(writer => {
|
||||
typeChecker.writeSymbol(symbol, enclosingDeclaration, meaning, flags | SymbolFormatFlags.UseAliasDefinedOutsideCurrentScope, writer);
|
||||
});
|
||||
}
|
||||
|
||||
export function signatureToDisplayParts(typechecker: TypeChecker, signature: Signature, enclosingDeclaration?: Node, flags?: TypeFormatFlags): SymbolDisplayPart[] {
|
||||
export function signatureToDisplayParts(typechecker: TypeChecker, signature: Signature, enclosingDeclaration?: Node, flags: TypeFormatFlags = TypeFormatFlags.None): SymbolDisplayPart[] {
|
||||
flags |= TypeFormatFlags.UseAliasDefinedOutsideCurrentScope | TypeFormatFlags.MultilineObjectLiterals | TypeFormatFlags.WriteTypeArgumentsOfSignature | TypeFormatFlags.OmitParameterModifiers;
|
||||
return mapToDisplayParts(writer => {
|
||||
typechecker.writeSignature(signature, enclosingDeclaration, flags, /*signatureKind*/ undefined, writer);
|
||||
@@ -1479,7 +1484,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
export function isImportOrExportSpecifierName(location: Node): location is Identifier {
|
||||
return location.parent &&
|
||||
return !!location.parent &&
|
||||
(location.parent.kind === SyntaxKind.ImportSpecifier || location.parent.kind === SyntaxKind.ExportSpecifier) &&
|
||||
(<ImportOrExportSpecifier>location.parent).propertyName === location;
|
||||
}
|
||||
@@ -1503,7 +1508,7 @@ namespace ts {
|
||||
|
||||
export function scriptKindIs(fileName: string, host: LanguageServiceHost, ...scriptKinds: ScriptKind[]): boolean {
|
||||
const scriptKind = getScriptKind(fileName, host);
|
||||
return forEach(scriptKinds, k => k === scriptKind);
|
||||
return some(scriptKinds, k => k === scriptKind);
|
||||
}
|
||||
|
||||
export function getScriptKind(fileName: string, host?: LanguageServiceHost): ScriptKind {
|
||||
@@ -1529,13 +1534,13 @@ namespace ts {
|
||||
* WARNING: This is an expensive operation and is only intended to be used in refactorings
|
||||
* and code fixes (because those are triggered by explicit user actions).
|
||||
*/
|
||||
export function getSynthesizedDeepClone<T extends Node>(node: T | undefined, includeTrivia = true): T | undefined {
|
||||
const clone = node && getSynthesizedDeepCloneWorker(node);
|
||||
export function getSynthesizedDeepClone<T extends Node | undefined>(node: T, includeTrivia = true): T {
|
||||
const clone = node && getSynthesizedDeepCloneWorker(node as NonNullable<T>);
|
||||
if (clone && !includeTrivia) suppressLeadingAndTrailingTrivia(clone);
|
||||
return clone;
|
||||
}
|
||||
|
||||
function getSynthesizedDeepCloneWorker<T extends Node>(node: T): T | undefined {
|
||||
function getSynthesizedDeepCloneWorker<T extends Node>(node: T): T {
|
||||
const visited = visitEachChild(node, getSynthesizedDeepClone, nullTransformationContext);
|
||||
if (visited === node) {
|
||||
// This only happens for leaf nodes - internal nodes always see their children change.
|
||||
@@ -1552,10 +1557,12 @@ namespace ts {
|
||||
// PERF: As an optimization, rather than calling getSynthesizedClone, we'll update
|
||||
// the new node created by visitEachChild with the extra changes getSynthesizedClone
|
||||
// would have made.
|
||||
visited.parent = undefined;
|
||||
visited.parent = undefined!;
|
||||
return visited;
|
||||
}
|
||||
|
||||
export function getSynthesizedDeepClones<T extends Node>(nodes: NodeArray<T>, includeTrivia?: boolean): NodeArray<T>;
|
||||
export function getSynthesizedDeepClones<T extends Node>(nodes: NodeArray<T> | undefined, includeTrivia?: boolean): NodeArray<T> | undefined;
|
||||
export function getSynthesizedDeepClones<T extends Node>(nodes: NodeArray<T> | undefined, includeTrivia = true): NodeArray<T> | undefined {
|
||||
return nodes && createNodeArray(nodes.map(n => getSynthesizedDeepClone(n, includeTrivia)), nodes.hasTrailingComma);
|
||||
}
|
||||
@@ -1585,7 +1592,7 @@ namespace ts {
|
||||
addEmitFlagsRecursively(node, EmitFlags.NoTrailingComments, getLastChild);
|
||||
}
|
||||
|
||||
function addEmitFlagsRecursively(node: Node, flag: EmitFlags, getChild: (n: Node) => Node) {
|
||||
function addEmitFlagsRecursively(node: Node, flag: EmitFlags, getChild: (n: Node) => Node | undefined) {
|
||||
addEmitFlags(node, flag);
|
||||
const child = getChild(node);
|
||||
if (child) addEmitFlagsRecursively(child, flag, getChild);
|
||||
|
||||
Reference in New Issue
Block a user