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

Refactoring support by RyanCavanaugh · Pull Request #15569 · microsoft/TypeScript · GitHub

Refactoring support - #15569

Merged
Ryan Cavanaugh (RyanCavanaugh) merged 1 commit into
microsoft:masterfrom
RyanCavanaugh:new_refactor
May 19, 2017
Merged

Refactoring support#15569
Ryan Cavanaugh (RyanCavanaugh) merged 1 commit into
microsoft:masterfrom
RyanCavanaugh:new_refactor

Conversation

Copy link
Copy Markdown
Member

Picks up where #14624 left off.

Copy link
Copy Markdown
Member Author

Anyone want to take a look? The VS side is about to merge

Comment thread src/compiler/types.ts Outdated
Warning,
Error,
Message,
CodeFix

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 Suggestion.

Copy link
Copy Markdown
Member 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

Removed

Comment thread src/server/protocol.ts Outdated
export type GetApplicableRefactorsRequestArgs = FileLocationOrRangeRequestArgs;

export interface ApplicableRefactorInfo {
refactorName: string;

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

just name

Comment thread src/server/protocol.ts Outdated
/* @internal */
export type GetCodeFixesFull = "getCodeFixes-full";
export type GetSupportedCodeFixes = "getSupportedCodeFixes";
export type GetCodeFixDiagnostics = "getCodeFixDiagnostics";

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

getSuggestionDiagnostics

Copy link
Copy Markdown
Member 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

Removed

});

function createCodeFixDiagnosticIfApplicable(node: Node, context: CodeFixDiagnoseContext): Diagnostic | undefined {
if (!isSourceFileJavaScript(context.boundSourceFile)) {

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

this is not going to scale as we add code fixes. we can not call every code fix on every node on the tree, we need a more efficient way.
We could make codeFix register a SyntaxKind it is interested in, this will save us the dispatch on every node at least.
Alternatively, we can have the code fix return a Boolean whether to keep walking or not, this way we avoid walking expressions that we do not care about.

Copy link
Copy Markdown
Member 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

Codefix feature removed

Comment thread src/services/codeFixProvider.ts Outdated
}

export function getCodeFixDiagnosticsForNode(context: CodeFixDiagnoseContext, node: Node): Diagnostic[] | undefined {
let result: Diagnostic[];

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 think we need to optimize this function and getCodeFixDiagnostics.


const checker = context.program.getTypeChecker();
const symbol = checker.getSymbolAtLocation(node);
if (isClassLikeSymbol(symbol)) {

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 say this should be limited to the declaration, not on every reference.

I would also say you do not need the checker here.

Comment thread src/services/codeFixProvider.ts Outdated
export interface CodeFix {
errorCodes: number[];
getCodeActions(context: CodeFixContext): CodeAction[] | undefined;
createCodeFixDiagnosticIfApplicable?(node: Node, context: CodeFixDiagnoseContext): Diagnostic | undefined;

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

Ideally we want this to be syntactic in nature, passing in the program allows for getting the checker. this can be expensive if the codeFix author do not know what they are doing, consider not passing in the program, but just a sourceFile and options.

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 also want to use the same mechanism for refactorings. a refactoring should have isApplicable, and getCodeActions. I would recommend switching this into isApplicable, and an optional diagnostic message.

Comment thread src/services/refactorProvider.ts Outdated
getCodeActions(context: RefactorContext, positionOrRange: number | TextRange): CodeAction[];

/** A fast syntactic check to see if the refactor is applicable at given position. */
isApplicableForPositionOrRange(context: LightRefactorContext, positionOrRange: number | TextRange): boolean;

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

consider unifying this with the codeFix isApplicable. ideally we can have one implementation that serves as both a refactor and a codefix + suggestion provider.


const asyncSuffixRefactor: Refactor = {
name: "Add Async suffix",
description: "Add an 'Async' suffix to async function declarations",

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 be a diagnostics message for localizability.

const token = getTokenAtPosition(nonBoundSourceFile, tokenPos);

let node = token;
while (node) {

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

It is kind of random that on any expression i can refactor the containing function to include async. i would say this has to be on function/method declaration at least.

Comment thread src/services/refactorProvider.ts Outdated
getCodeActions(context: RefactorContext, positionOrRange: number | TextRange): CodeAction[];

/** A fast syntactic check to see if the refactor is applicable at given position. */
isApplicableForPositionOrRange(context: QueryRefactorContext, positionOrRange: number | TextRange): boolean;

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

just isApplicable, the positionOrRange is implied from the arguments.

/* @internal */
namespace ts.refactor {
const asyncSuffixRefactor: Refactor = {
name: "Add Async suffix",

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

This should be in diagnostics

Copy link
Copy Markdown
Member 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

Removed this refactor

namespace ts.refactor {
const asyncSuffixRefactor: Refactor = {
name: "Add Async suffix",
description: "Add an 'Async' suffix to async function declarations",

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 be in diagnostics to ensure localizatability.

}];
}

function isApplicableForPositionOrRange(context: RefactorContext, positionOrRange: number | TextRange): boolean {

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

kinda silly comment, but can we have (startPosition, endPoisition) instead of positionOrRange? every refactor author has to write the same check typeof positionOrRange === "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

Actually why not just put these on the RefactorContext? we put the errorCode on the codeFix context.

Copy link
Copy Markdown
Member 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

Makes sense


let node = token;
while (node) {
if (node.kind === SyntaxKind.FunctionDeclaration) {

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 use isNameOfFunctionDeclaration or something similar.

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 check if token is one of identifier, function keyword, public, private, protected, or static , and their parent is a FunctionDeclatation or MethodDeclaration.

Copy link
Copy Markdown
Member 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

File removed

}

// all static members are stored in the "exports" array of symbol
if (symbol.exports) {

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

Is this intended for a .ts or a .js file?

I think it is a .js file, since the binding for the special properties do not work in .ts files any way.

If my understanding is correct, then for static members we can not just add declarations for them, this will result in invalid .js class.

this also applies to the property declarations and assignments..

If we want this to work in a .ts file, then we need to do something with the inference to make it work first.

I would also recommend adding a check at the top of isApplicable to return if !inJavaScriptFile(node)

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

also for member initialization, I wounder if we can even do these correctellly...

var c = function() { this.list.push(1); }
c.prototype.list = [];

is not the same as:

class c {
    constructor() { this.list.push(1); }
    list = [];

let a side that it is not valid JS strictly speaking.

Copy link
Copy Markdown
Member 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

Fixed these up. Non-func-expr things remain as assignments following the class body

Comment thread src/services/services.ts Outdated
positionOrRange: number | TextRange,
refactorName: string): CodeAction[] | undefined {

const 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

consider in-lining the const in the call and using the contextual type instead.

positionOrRange: number | TextRange): ApplicableRefactorInfo[] | undefined {

let results: ApplicableRefactorInfo[];
refactors.forEach(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

I would check the cancellation token here.

Comment thread src/services/refactorProvider.ts Outdated
program: Program;
}

export interface RefactorContext extends QueryRefactorContext {

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

what is the value of the split here?

Comment thread src/services/refactorProvider.ts Outdated

export interface RefactorContext extends QueryRefactorContext {
newLineCharacter: string;
rulesProvider: formatting.RulesProvider;

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

what about cancellation token?

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

consider exposing CodeFixContext minus errorCode.

Comment thread src/server/protocol.ts

export type GetApplicableRefactors = "getApplicableRefactors";
export type GetRefactorCodeActions = "getRefactorCodeActions";
export type GetRefactorCodeActionsFull = "getRefactorCodeActions-full";

Mohamed Hegazy (mhegazy) May 19, 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

This should be marked as /* @internal */

Comment thread src/server/protocol.ts

export type RefactorCodeActions = {
actions: protocol.CodeAction[];
renameLocation?: 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

A comment here would be good.

program: Program;
newLineCharacter: string;
rulesProvider?: formatting.RulesProvider;
cancellationToken?: CancellationToken;

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

why is this optional?

endPosition?: number;
program: Program;
newLineCharacter: string;
rulesProvider?: formatting.RulesProvider;

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

why is this optional?

This was referenced May 19, 2017
Matt Bierner (mjbvz) pushed a commit to mjbvz/vscode that referenced this pull request Jun 16, 2017
Fixes microsoft#25739, from microsoft/TypeScript#15569

Prototype of refactoring support for ts 2.4
Matt Bierner (mjbvz) pushed a commit to microsoft/vscode that referenced this pull request Jun 16, 2017
* Prototype TS/JS Refactoring Provider

Fixes #25739, from microsoft/TypeScript#15569

Prototype of refactoring support for ts 2.4

* Adding error reporting

* Updating for new API

* show quick pick for non-inlinable refactrings
Anantha Kumaran (ananthakumaran) added a commit to ananthakumaran/tide that referenced this pull request Jul 8, 2017
Anantha Kumaran (ananthakumaran) added a commit to ananthakumaran/tide that referenced this pull request Jul 30, 2017
Microsoft (microsoft) locked and limited conversation to collaborators Jun 14, 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.

3 participants


Back | FazBrowse Home | New Git URL