Merge pull request #26749 from uniqueiniquity/getWholeType

Use correct type for async refactoring diagnostics
This commit is contained in:
Benjamin Lichtman
2018-08-31 09:09:25 -07:00
committed by GitHub
9 changed files with 106 additions and 10 deletions
@@ -42,7 +42,18 @@ namespace ts.codefix {
function convertToAsyncFunction(changes: textChanges.ChangeTracker, sourceFile: SourceFile, position: number, checker: TypeChecker, context: CodeFixContextBase): void {
// get the function declaration - returns a promise
const functionToConvert: FunctionLikeDeclaration = getContainingFunction(getTokenAtPosition(sourceFile, position)) as FunctionLikeDeclaration;
const tokenAtPosition = getTokenAtPosition(sourceFile, position);
let functionToConvert: FunctionLikeDeclaration | undefined;
// if the parent of a FunctionLikeDeclaration is a variable declaration, the convertToAsync diagnostic will be reported on the variable name
if (isIdentifier(tokenAtPosition) && isVariableDeclaration(tokenAtPosition.parent) &&
tokenAtPosition.parent.initializer && isFunctionLikeDeclaration(tokenAtPosition.parent.initializer)) {
functionToConvert = tokenAtPosition.parent.initializer;
}
else {
functionToConvert = tryCast(getContainingFunction(getTokenAtPosition(sourceFile, position)), isFunctionLikeDeclaration);
}
if (!functionToConvert) {
return;
}
+4 -3
View File
@@ -3,7 +3,7 @@ namespace ts {
export function computeSuggestionDiagnostics(sourceFile: SourceFile, program: Program, cancellationToken: CancellationToken): DiagnosticWithLocation[] {
program.getSemanticDiagnostics(sourceFile, cancellationToken);
const diags: DiagnosticWithLocation[] = [];
const checker = program.getDiagnosticsProducingTypeChecker();
const checker = program.getTypeChecker();
if (sourceFile.commonJsModuleIndicator &&
(programContainsEs6Modules(program) || compilerOptionsIndicateEs6Modules(program.getCompilerOptions())) &&
@@ -115,11 +115,12 @@ namespace ts {
function addConvertToAsyncFunctionDiagnostics(node: FunctionLikeDeclaration, checker: TypeChecker, diags: DiagnosticWithLocation[]): void {
const functionType = node.type ? checker.getTypeFromTypeNode(node.type) : undefined;
if (isAsyncFunction(node) || !node.body || !functionType) {
if (isAsyncFunction(node) || !node.body) {
return;
}
const functionType = checker.getTypeAtLocation(node);
const callSignatures = checker.getSignaturesOfType(functionType, SignatureKind.Call);
const returnType = callSignatures.length ? checker.getReturnTypeOfSignature(callSignatures[0]) : undefined;
@@ -319,7 +319,7 @@ interface String { charAt: any; }
interface Array<T> {}`
};
function testConvertToAsyncFunction(caption: string, text: string, baselineFolder: string, description: DiagnosticMessage, includeLib?: boolean) {
function testConvertToAsyncFunction(caption: string, text: string, baselineFolder: string, diagnosticDescription: DiagnosticMessage, codeFixDescription: DiagnosticMessage, includeLib?: boolean) {
const t = getTest(text);
const selectionRange = t.ranges.get("selection")!;
if (!selectionRange) {
@@ -361,12 +361,14 @@ interface Array<T> {}`
};
const diagnostics = languageService.getSuggestionDiagnostics(f.path);
const diagnostic = find(diagnostics, diagnostic => diagnostic.messageText === description.message);
assert.isNotNull(diagnostic);
const diagnostic = find(diagnostics, diagnostic => diagnostic.messageText === diagnosticDescription.message);
assert.exists(diagnostic);
assert.equal(diagnostic!.start, context.span.start);
assert.equal(diagnostic!.length, context.span.length);
const actions = codefix.getFixes(context);
const action = find(actions, action => action.description === description.message)!;
assert.isNotNull(action);
const action = find(actions, action => action.description === codeFixDescription.message)!;
assert.exists(action);
const data: string[] = [];
data.push(`// ==ORIGINAL==`);
@@ -423,6 +425,10 @@ interface Array<T> {}`
_testConvertToAsyncFunction("convertToAsyncFunction_basic", `
function [#|f|](): Promise<void>{
return fetch('https://typescriptlang.org').then(result => { console.log(result) });
}`);
_testConvertToAsyncFunction("convertToAsyncFunction_basicNoReturnTypeAnnotation", `
function [#|f|]() {
return fetch('https://typescriptlang.org').then(result => { console.log(result) });
}`);
_testConvertToAsyncFunction("convertToAsyncFunction_basicWithComments", `
function [#|f|](): Promise<void>{
@@ -436,6 +442,10 @@ function [#|f|](): Promise<void>{
_testConvertToAsyncFunction("convertToAsyncFunction_ArrowFunction", `
[#|():Promise<void> => {|]
return fetch('https://typescriptlang.org').then(result => console.log(result));
}`);
_testConvertToAsyncFunction("convertToAsyncFunction_ArrowFunctionNoAnnotation", `
[#|() => {|]
return fetch('https://typescriptlang.org').then(result => console.log(result));
}`);
_testConvertToAsyncFunction("convertToAsyncFunction_Catch", `
function [#|f|]():Promise<void> {
@@ -1178,11 +1188,17 @@ function [#|f|]() {
}
`);
_testConvertToAsyncFunction("convertToAsyncFunction_simpleFunctionExpression", `
const [#|foo|] = function () {
return fetch('https://typescriptlang.org').then(result => { console.log(result) });
}
`);
});
function _testConvertToAsyncFunction(caption: string, text: string) {
testConvertToAsyncFunction(caption, text, "convertToAsyncFunction", Diagnostics.Convert_to_async_function, /*includeLib*/ true);
testConvertToAsyncFunction(caption, text, "convertToAsyncFunction", Diagnostics.This_may_be_converted_to_an_async_function, Diagnostics.Convert_to_async_function, /*includeLib*/ true);
}
function _testConvertToAsyncFunctionFailed(caption: string, text: string) {
@@ -0,0 +1,11 @@
// ==ORIGINAL==
/*[#|*/() => {/*|]*/
return fetch('https://typescriptlang.org').then(result => console.log(result));
}
// ==ASYNC FUNCTION::Convert to async function==
async () => {
const result = await fetch('https://typescriptlang.org');
return console.log(result);
}
@@ -0,0 +1,11 @@
// ==ORIGINAL==
/*[#|*/() => {/*|]*/
return fetch('https://typescriptlang.org').then(result => console.log(result));
}
// ==ASYNC FUNCTION::Convert to async function==
async () => {
const result = await fetch('https://typescriptlang.org');
return console.log(result);
}
@@ -0,0 +1,11 @@
// ==ORIGINAL==
function /*[#|*/f/*|]*/() {
return fetch('https://typescriptlang.org').then(result => { console.log(result) });
}
// ==ASYNC FUNCTION::Convert to async function==
async function f() {
const result = await fetch('https://typescriptlang.org');
console.log(result);
}
@@ -0,0 +1,11 @@
// ==ORIGINAL==
function /*[#|*/f/*|]*/() {
return fetch('https://typescriptlang.org').then(result => { console.log(result) });
}
// ==ASYNC FUNCTION::Convert to async function==
async function f() {
const result = await fetch('https://typescriptlang.org');
console.log(result);
}
@@ -0,0 +1,12 @@
// ==ORIGINAL==
const /*[#|*/foo/*|]*/ = function () {
return fetch('https://typescriptlang.org').then(result => { console.log(result) });
}
// ==ASYNC FUNCTION::Convert to async function==
const foo = async function () {
const result = await fetch('https://typescriptlang.org');
console.log(result);
}
@@ -0,0 +1,12 @@
// ==ORIGINAL==
const /*[#|*/foo/*|]*/ = function () {
return fetch('https://typescriptlang.org').then(result => { console.log(result) });
}
// ==ASYNC FUNCTION::Convert to async function==
const foo = async function () {
const result = await fetch('https://typescriptlang.org');
console.log(result);
}