-
Notifications
You must be signed in to change notification settings - Fork 12.6k
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
Extract method #16960
Extract method #16960
Changes from 16 commits
be27a1a
e798257
bf176a6
0130ebb
bbf5cd7
9dd6bef
f21b7ae
674b1bf
9367473
1ea9972
1787fa8
fb89c00
4aef5e7
b5c5c40
b1fa49f
825237b
aa6f3aa
b7e4451
419a4c2
4218738
6d2bc90
9a24549
271ecb1
bdefcc3
6428b1e
8af8ac2
ede6671
55b28ad
2d9eaa9
2f2c780
63193da
889292a
e229d42
7b2dd8a
bf6c0a9
3424312
ff18df3
7f29fcd
d39d95b
dda5496
e88ff21
bd80005
ff716d0
1291cfd
a26790f
56e1d6d
7f3a0a8
003cd0a
a76664c
42e0652
46a84c3
a97ab93
37ae957
2adb2b3
ba37830
4dafb40
c1c7e83
a4c41b8
b5a88c1
568d5f6
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2645,9 +2645,8 @@ namespace ts { | |
* Does not include properties of primitive types. | ||
*/ | ||
/* @internal */ getAllPossiblePropertiesOfType(type: Type): Symbol[]; | ||
|
||
/* @internal */ resolveName(name: string, location: Node, meaning: SymbolFlags): Symbol; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What happened to There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The compiler doesn't have |
||
/* @internal */ getJsxNamespace(): string; | ||
/* @internal */ resolveNameAtLocation(location: Node, name: string, meaning: SymbolFlags): Symbol | undefined; | ||
} | ||
|
||
export enum NodeBuilderFlags { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -187,6 +187,9 @@ namespace FourSlash { | |
|
||
// The current caret position in the active file | ||
public currentCaretPosition = 0; | ||
// The position of the end of the current selection, or -1 if nothing is selected | ||
public selectionEnd = -1; | ||
|
||
public lastKnownMarker = ""; | ||
|
||
// The file that's currently 'opened' | ||
|
@@ -433,11 +436,19 @@ namespace FourSlash { | |
|
||
public goToPosition(pos: number) { | ||
this.currentCaretPosition = pos; | ||
this.selectionEnd = -1; | ||
} | ||
|
||
public select(startMarker: string, endMarker: string) { | ||
const start = this.getMarkerByName(startMarker), end = this.getMarkerByName(endMarker); | ||
this.goToPosition(start.position); | ||
this.selectionEnd = end.position; | ||
} | ||
|
||
public moveCaretRight(count = 1) { | ||
this.currentCaretPosition += count; | ||
this.currentCaretPosition = Math.min(this.currentCaretPosition, this.getFileContent(this.activeFile.fileName).length); | ||
this.selectionEnd = -1; | ||
} | ||
|
||
// Opens a file given its 0-based index or fileName | ||
|
@@ -2748,6 +2759,25 @@ namespace FourSlash { | |
} | ||
} | ||
|
||
public verifyRefactorAvailable(negative: boolean, name?: string) { | ||
const selection = { | ||
pos: this.currentCaretPosition, | ||
end: this.selectionEnd === -1 ? this.currentCaretPosition : this.selectionEnd | ||
}; | ||
|
||
let refactors = this.languageService.getApplicableRefactors(this.activeFile.fileName, selection) || []; | ||
if (name) { | ||
refactors = refactors.filter(r => r.name === name); | ||
} | ||
const isAvailable = refactors.length > 0; | ||
if (negative && isAvailable) { | ||
this.raiseError(`verifyApplicableRefactorAvailableForRange failed - expected no refactor but found some.`); | ||
} | ||
if (!negative && !isAvailable) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
else if |
||
this.raiseError(`verifyApplicableRefactorAvailableForRange failed - expected a refactor but found none.`); | ||
} | ||
} | ||
|
||
public verifyApplicableRefactorAvailableForRange(negative: boolean) { | ||
const ranges = this.getRanges(); | ||
if (!(ranges && ranges.length === 1)) { | ||
|
@@ -2764,6 +2794,20 @@ namespace FourSlash { | |
} | ||
} | ||
|
||
public applyRefactor(refactorName: string, actionName: string) { | ||
const range = { pos: this.currentCaretPosition, end: this.selectionEnd === -1 ? this.currentCaretPosition : this.selectionEnd }; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Duplicated from above? |
||
const refactors = this.languageService.getApplicableRefactors(this.activeFile.fileName, range); | ||
const refactor = ts.find(refactors, r => r.name === refactorName); | ||
if (!refactor) { | ||
this.raiseError(`The expected refactor: ${refactorName} is not available at the marker location.`); | ||
} | ||
|
||
const editInfo = this.languageService.getEditsForRefactor(this.activeFile.fileName, this.formatCodeSettings, range, refactorName, actionName); | ||
for (const edit of editInfo.edits) { | ||
this.applyEdits(edit.fileName, edit.textChanges); | ||
} | ||
} | ||
|
||
public verifyFileAfterApplyingRefactorAtMarker( | ||
markerName: string, | ||
expectedContent: string, | ||
|
@@ -3505,6 +3549,10 @@ namespace FourSlashInterface { | |
public file(indexOrName: any, content?: string, scriptKindName?: string): void { | ||
this.state.openFile(indexOrName, content, scriptKindName); | ||
} | ||
|
||
public select(startMarker: string, endMarker: string) { | ||
this.state.select(startMarker, endMarker); | ||
} | ||
} | ||
|
||
export class VerifyNegatable { | ||
|
@@ -3626,6 +3674,10 @@ namespace FourSlashInterface { | |
public applicableRefactorAvailableForRange() { | ||
this.state.verifyApplicableRefactorAvailableForRange(this.negative); | ||
} | ||
|
||
public refactorAvailable(name?: string) { | ||
this.state.verifyRefactorAvailable(this.negative, name); | ||
} | ||
} | ||
|
||
export class Verify extends VerifyNegatable { | ||
|
@@ -4017,6 +4069,10 @@ namespace FourSlashInterface { | |
public disableFormatting() { | ||
this.state.enableFormatting = false; | ||
} | ||
|
||
public applyRefactor(refactorName: string, actionName: string) { | ||
this.state.applyRefactor(refactorName, actionName); | ||
} | ||
} | ||
|
||
export class Debug { | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this the same as
resolveNameAtLocation
, but with a changed argument order and no looking up of parse tree nodes (I can only assume so it works on synthesized nodes with parent pointers setup)? Can we not just remove the looking up of parse tree nodes inresolveNameAtLocation
if that's the case? Oh,nameArg
is alsoundefined
. Can that not just be added as an optional parameter to this existing function?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@rbuckton would know authoritatively, but as I understand it, we check
isParseTreeNode
on public API requests because the checker does not work well with synthesized nodes, since we don't perform binding on synthesized nodes as part of transforms (for performance reasons?) and we may inspect the literal text as part of some checker operations. That is, the checker API is only supposed to work with trees parsed and bound from an actual source file.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@aozgaa is correct. If the checker receives a node that did not originate from a parse tree, we attempt to find the parse tree node from which it was created. Passing in a synthesized node to the checker without a parse-tree check will likely result in compiler crashes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That said,
resolveNameAtLocation
(nee.resolveName
) is marked/* @internal */
and isn't used in transforms. The guard is mostly present in case we decide to use it at some point down the road.