FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

Add infrastructure for refactors by zhengbli · Pull Request #14624 · microsoft/TypeScript · GitHub

Add infrastructure for refactors - #14624

Closed
Zhengbo Li (zhengbli) wants to merge 16 commits into
microsoft:masterfrom
zhengbli:refactor_only
Closed

Add infrastructure for refactors#14624
Zhengbo Li (zhengbli) wants to merge 16 commits into
microsoft:masterfrom
zhengbli:refactor_only

Conversation

Zhengbo Li (zhengbli) commented Mar 13, 2017
edited
Loading

Copy link
Copy Markdown

This PR adds the infrastructure for refactors.

The PR adds one new kind of code fixes as well as refactors:

  1. "diagnostic-generating code fixes": a special kind of code fixes that would generate non-error diagnostics. After normal syntactic check and semantic check, the language service will do an extra pass of the AST to get the non-error diagnostics generated by registered "diagnostic-generating code fixes". Then when the user interacts with the new diagnostics in code, a query for corresponding code actions will be triggered, just like with other code fixes.

  2. "refactors": to get a refactor it is a two-step procedure. First, the editor will ask about all "applicable refactor info" at a given location / range, the returned "applicable refactor info" would only contain basic information like refactor names, it wouldn't compute the code actions yet. Then after the user chose a particular refactor, then the editor will send another request to compute the corresponding code actions.

// the semanticDiag message
host.runQueuedImmediateCallbacks();
assert.equal(host.getOutput().length, 2, "expect 2 messages");
assert.equal(host.getOutput().length, 1, "expect 1 messages");

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

"messages" should be "message"

Comment thread src/server/client.ts Outdated
}

getRefactorDiagnostics(fileName: string, range?: TextRange): RefactorDiagnostic[] {
const startLineOffset = this.positionToOneBasedLineOffset(fileName, range.pos);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

Does this crash if range === undefined ?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

Here the range is not supposed to be nullable, as we only use it to test the session API GetRefactorsForRange. Will update

Comment thread src/server/protocol.ts Outdated
* Instances of this interface specify errorcodes on a specific location in a sourcefile.
*/
export interface CodeFixRequestArgs extends FileRequestArgs {
export interface TextRangeRequestArgs extends FileRequestArgs {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

Can you name the first two members line and offset to more closely coincide with FileLocationRequestArgs andLocation? Or use a Location for the start and end?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

Maybe FileRangeRequestArgs would fit better. But using location for start and end would be an unnecessary breaking change for editors already consuming this type.

Comment thread src/server/session.ts Outdated
return { startPosition, endPosition };

function getStartPosition() {
return args.startPosition !== undefined ? args.startPosition : scriptInfo.lineOffsetToPosition(args.startLine, args.startOffset);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

Do you want to save the result in args.startPosition (resp. args.endPosition)?

/* @internal */
namespace ts {
interface BaseRefactor {
/** Description of the refactor to display in the UI of the editor */

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

should this have a property canBeSuggested: boolean; ?

export type Refactor = SuggestableRefactor | NonSuggestableRefactor;

export interface LightRefactorContext {
nonBoundSourceFile: SourceFile;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

Can you add a comment explaining what bound and nonBound means?

Comment thread src/services/refactorProvider.ts Outdated
return results;
}

export function getSuggestedRefactorDiagnosticsForNode(node: Node, context: RefactorContext) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

Would it be right to name this getSuggestable...? That would be more consistent with the naming of the interfaces.

Comment thread src/services/services.ts Outdated
}
}

function getCodeActionsForRefactorAtPosition(

Arthur Ozga (aozgaa) Mar 17, 2017
edited
Loading

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

Do we have a convention for when we split function parameters across multiple lines?

Zhengbo Li (zhengbli) Mar 20, 2017
edited
Loading

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

I don't think so, though normally i do that when I have to use the horizontal scroll bar on my laptop if putting all in one line.

Comment thread src/server/protocol.ts Outdated
refactorCode: number;
}

export interface GetCodeActionsForRefactorResponse extends Response {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

do not use an array. make it an map.

Comment thread src/server/protocol.ts Outdated
position?: number;
}

export namespace Refactor {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

we do not use namespaces anywhere else.

Comment thread src/server/protocol.ts Outdated
}

export interface ApplicableRefactorInfo {
refactorKind: number;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

i would call this name and make it string.

Comment thread src/server/protocol.ts Outdated
}

export interface GetApplicableRefactorsResponse extends Response {
body?: ApplicableRefactorInfo[];

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

i would make this an object instead of an array.

Comment thread src/server/protocol.ts Outdated

export interface GetRefactorCodeActionsRequestArgs extends FileLocationOrSpanWithPositionRequestArgs {
/* The kind of the applicable refactor */
refactorKinds?: number[];

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

probally just one refactoring to ask for code actions for

Comment thread src/server/protocol.ts Outdated
/* The kind of the applicable refactor */
refactorKinds?: number[];
/* The diagnostic code of a refactor diagnostic */
diagnosticCodes?: number[];

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

do not think we need this, it should be covered by getCodeActions

Comment thread src/server/session.ts
const { startPosition, endPosition } = this.getStartAndEndPosition(args, scriptInfo);
textRange = { pos: startPosition, end: endPosition };
}
return { position, textRange };

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

position may be undefined, is this intended? Initialize at line 1450 if so

Comment thread src/server/session.ts Outdated
return args.endPosition !== undefined ? args.endPosition : scriptInfo.lineOffsetToPosition(args.endLine, args.endOffset);
}
private getStartAndEndPosition(args: protocol.FileRangeRequestArgs, scriptInfo: ScriptInfo) {
const startPosition = args.startPosition !== undefined

Ryan Cavanaugh (RyanCavanaugh) Apr 18, 2017
edited
Loading

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

This is really confusing, can we just use a normal if here

export function getCodeFixDiagnosticsForNode(context: CodeFixDiagnoseContext, node: Node): Diagnostic[] | undefined {
let result: Diagnostic[];
for (const codeFix of diagnosticGeneratingCodeFixes) {
const newDiag = codeFix.createCodeFixDiagnosticIfApplicable(node, context);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

This member is declared as optional, but isn't checked for undefined in this method

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

in line 41 it already checked the existence of createCodeFixDiagnosticIfApplicable

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

👍

isApplicableForPositionOrRange(context: LightRefactorContext, positionOrRange: number | TextRange): boolean;
}

export interface LightRefactorContext {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

Comment defining what "Light" means

return results;
}

export function getRefactorCodeActions(

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

Why does this return an empty array vs getApplicableRefactors returns undefined if the array would have been empty?

Copy link
Copy Markdown
Member

Should we add a trivial refactor with this just so we can have some testcases?

Copy link
Copy Markdown
Author

Sure, I'm adding one now will update soon

Copy link
Copy Markdown
Author

I added two things:

  1. a diagnostic-generating code fix: converting functions that has prototype assignment to ES6 classes
  2. a sample refactor: add Async suffix to async function declarations

Copy link
Copy Markdown
Member

Mohamed Hegazy (@mhegazy) any other comments?

Copy link
Copy Markdown
Contributor

closing in favor of #15569

Microsoft (microsoft) locked and limited conversation to collaborators Jun 19, 2018
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants


Back | FazBrowse Home | New Git URL