Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Quick fix for functions lacking return expressions #26434

Merged
merged 28 commits into from
Apr 2, 2020

Conversation

Kingwl
Copy link
Contributor

@Kingwl Kingwl commented Aug 14, 2018

Fixes #25751

this pr surmise return type and check the Assignable

the code fix handle follow 4 cases:

    1. function like with return type annotation
    1. call expression with a function like parameter, and argument is a function like expression
    1. assignment with a type annotation, and initializer is a function like expression
    1. jsx property assignment whitch can surmise the return type

and surmise follow 3 rules:

    1. only one expression statement in Block body and the type is assignable
    1. only one Block in Block body and the block only contains one labeled statement, make an object literal generated from label and statement, and that is assignable
      eg:
function A () {
    { a: 'b' }
}

a => {
    { a: 'b' }
}
    1. declaration is arrow function and only one labeled statement in Block body, make an object literal generated from label and statement, and that is assignable
      eg:
a => {
    a: 'b'
}

for first case, i try to get the return type from type annotation and compare with type of expression statement
second case, i try to get the parameter from the signature and check the Assignable with the fixed type( after insert the return type)
third case, i try to get the type of the initializer and check the Assignable type of from the variable declaration type annotation ( after insert the return type)

some thing need todo:

    1. add test case of fix all
    1. add test case of actions
    1. add more edge case for fix (eg. object literal or comma with the paren )
    1. add more test for labeled statement fix
    1. add jsx support
    1. add property assign / class property declartion support

@Kingwl Kingwl changed the title [WIP] [Review need] Return value surmise Return value surmise Aug 20, 2018
@RyanCavanaugh RyanCavanaugh added this to the TypeScript 3.2 milestone Sep 17, 2018
@RyanCavanaugh
Copy link
Member

@DanielRosenwasser I'd like to talk about this one offline

@Kingwl
Copy link
Contributor Author

Kingwl commented Jan 30, 2019

any offline update here? 🤣

@Kingwl
Copy link
Contributor Author

Kingwl commented Apr 1, 2019

🙋🏻‍♂️

@DanielRosenwasser
Copy link
Member

DanielRosenwasser commented Apr 2, 2019

If I recall correctly, Ryan was just concerned that providing too many refactorings and quick fixes could become "noisy". I don't think that that should block this PR since these are legitimate fixes that can help users learn more about the language.

@Kingwl
Copy link
Contributor Author

Kingwl commented Apr 29, 2019

Maybe I could support more case:

function foo () {
  return // line feed
  {
    a: 1
  }
}

@DanielRosenwasser DanielRosenwasser changed the title Return value surmise Quick fix for functions lacking return expressions Apr 29, 2019
@Kingwl
Copy link
Contributor Author

Kingwl commented May 10, 2019

Could this get down on 3.5?

}

function checkFixedAssignableTo(checker: TypeChecker, declaration: FunctionLikeDeclaration, expr: Expression, type: Type, isFunctionType: boolean) {
return checker.isTypeAssignableTo(checker.getTypeAtLocation(isFunctionType ? updateFunctionLikeBody(declaration, createBlock([createReturn(expr)])) : expr), type);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@rbuckton is this going to cause any trouble? Here, the type-checker is going to jump into synthetic nodes.

"category": "Message",
"code": 95080
},
"Surmise all return value": {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've got to admit: I don't know what the word surmise means, and I don't know if users will either. What's the intent here?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"Correct all return expressions" would be best here

"surmise" is not in basic English vocabulary and we need to avoid it entirely for clarity's sake.

changes.replaceNode(sourceFile, declaration.body, createParen(expression));
}

function getActionForfixAddReturnStatement(context: CodeFixContext, declaration: FunctionLikeDeclaration, expression: Expression) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Upper-case on fix, here and below

Copy link
Member

@RyanCavanaugh RyanCavanaugh left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Kingwl Overall looking pretty good; just need a couple fixes here before merge. Thanks!

"category": "Message",
"code": 95080
},
"Surmise all return value": {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"Correct all return expressions" would be best here

"surmise" is not in basic English vocabulary and we need to avoid it entirely for clarity's sake.

@Kingwl
Copy link
Contributor Author

Kingwl commented Jan 9, 2020

@typescript-bot test this.

@typescript-bot
Copy link
Collaborator

typescript-bot commented Jan 9, 2020

Heya @Kingwl, I've started to run the extended test suite on this PR at 537e806. You can monitor the build here. It should now contribute to this PR's status checks.

@DanielRosenwasser
Copy link
Member

did you mean

@typescript-bot pack this

?

The tests shouldn't uncover anything since this is an editor feature, right?

@Kingwl
Copy link
Contributor Author

Kingwl commented Mar 18, 2020

@typescript-bot pack this.

@typescript-bot
Copy link
Collaborator

typescript-bot commented Mar 18, 2020

Heya @Kingwl, I've started to run the tarball bundle task on this PR at 7fe9a82. You can monitor the build here.

@typescript-bot
Copy link
Collaborator

typescript-bot commented Mar 18, 2020

Hey @Kingwl, I've packed this into an installable tgz. You can install it for testing by referencing it in your package.json like so:

{
    "devDependencies": {
        "typescript": "https://typescript.visualstudio.com/cf7ac146-d525-443c-b23c-0d58337efebc/_apis/build/builds/68505/artifacts?artifactName=tgz&fileId=8C63B8D64E32F09B6D654098D56F19BF5BD7814BCE0D6A377468DAB51806CFA502&fileName=/typescript-3.9.0-insiders.20200318.tgz"
    }
}

and then running npm install.


There is also a playground for this build.

@Kingwl
Copy link
Contributor Author

Kingwl commented Mar 24, 2020

Friendly ping @amcasey

@amcasey
Copy link
Member

amcasey commented Mar 24, 2020

@Kingwl The commits kept coming, so I figured I'd just wait for your ping. 😄

Copy link
Member

@amcasey amcasey left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I made some nit-picky comments, but it looks good. Tomorrow, I'll build and play with it. Thanks!

src/compiler/diagnosticMessages.json Outdated Show resolved Hide resolved
];

enum FixKind {
MissingReturnStatement,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Arguably, these are problem kinds. The corresponding fix kinds would be "AddReturnStatement" and "AddParentheses".

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are there only two kinds of fixes? Shouldn't there also be one for removing the braces?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And why not just use the fix IDs from above?

src/services/codefixes/returnValueCorrect.ts Outdated Show resolved Hide resolved
tests/cases/fourslash/codeFixSurmiseReturnValue1.ts Outdated Show resolved Hide resolved
}

function removeBlockBodyBrace(changes: textChanges.ChangeTracker, sourceFile: SourceFile, declaration: ArrowFunction, expression: Expression, withParen: boolean) {
changes.replaceNode(sourceFile, declaration.body, (withParen || needsParentheses(expression)) ? createParen(expression) : expression);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this going to delete comments? I'd be worried about anything between the end of the expression and the closing brace (and maybe things before the opening brace).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like it might delete {/*this comment*/1}. Not the end of the world.

Copy link
Member

@amcasey amcasey left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Feels good when I use it locally. Still some minor comments open about code cleanliness, but I'd basically merge this as-is.

src/compiler/diagnosticMessages.json Outdated Show resolved Hide resolved
}

function removeBlockBodyBrace(changes: textChanges.ChangeTracker, sourceFile: SourceFile, declaration: ArrowFunction, expression: Expression, withParen: boolean) {
changes.replaceNode(sourceFile, declaration.body, (withParen || needsParentheses(expression)) ? createParen(expression) : expression);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like it might delete {/*this comment*/1}. Not the end of the world.

//// const a: ((() => number) | (() => undefined)) = () => { 1 }

verify.codeFixAvailable([
{ description: 'Add a return statement' },
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, I think @andrewbranch did a bunch of work to make semicolons match the surrounding style automatically. 😄

@Kingwl
Copy link
Contributor Author

Kingwl commented Mar 26, 2020

@typescript-bot pack this.

@typescript-bot
Copy link
Collaborator

typescript-bot commented Mar 26, 2020

Heya @Kingwl, I've started to run the tarball bundle task on this PR at 8b332fe. You can monitor the build here.

@Kingwl
Copy link
Contributor Author

Kingwl commented Mar 27, 2020

@DanielRosenwasser Is there any possibility to get this done in 3.9?

@amcasey
Copy link
Member

amcasey commented Apr 2, 2020

@Kingwl Anything you're still working on (besides the merge conflict?) or shall I merge?

@Kingwl
Copy link
Contributor Author

Kingwl commented Apr 2, 2020

No, please feel free to merge

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
For Backlog Bug PRs that fix a backlog bug lib update PR modifies files in the `lib` folder
Projects
Archived in project
Development

Successfully merging this pull request may close these issues.

quick fix for function only contains one jsx element and have not the return statement
7 participants