mirror of
https://github.com/microsoft/TypeScript.git
synced 2025-11-18 17:21:48 +00:00
Merge pull request #31801 from andrewbranch/semicolons
Detect semicolons before writing from TextChanges
This commit is contained in:
+130
-104
@@ -847,9 +847,10 @@ namespace ts.textChanges {
|
||||
|
||||
/** Note: output node may be mutated input node. */
|
||||
export function getNonformattedText(node: Node, sourceFile: SourceFile | undefined, newLineCharacter: string): { text: string, node: Node } {
|
||||
const writer = new Writer(newLineCharacter);
|
||||
const omitTrailingSemicolon = !!sourceFile && !probablyUsesSemicolons(sourceFile);
|
||||
const writer = createWriter(newLineCharacter, omitTrailingSemicolon);
|
||||
const newLine = newLineCharacter === "\n" ? NewLineKind.LineFeed : NewLineKind.CarriageReturnLineFeed;
|
||||
createPrinter({ newLine, neverAsciiEscape: true }, writer).writeNode(EmitHint.Unspecified, node, sourceFile, writer);
|
||||
createPrinter({ newLine, neverAsciiEscape: true, omitTrailingSemicolon }, writer).writeNode(EmitHint.Unspecified, node, sourceFile, writer);
|
||||
return { text: writer.getText(), node: assignPositionsToNode(node) };
|
||||
}
|
||||
}
|
||||
@@ -887,143 +888,168 @@ namespace ts.textChanges {
|
||||
return nodeArray;
|
||||
}
|
||||
|
||||
class Writer implements EmitTextWriter, PrintHandlers {
|
||||
private lastNonTriviaPosition = 0;
|
||||
private readonly writer: EmitTextWriter;
|
||||
interface TextChangesWriter extends EmitTextWriter, PrintHandlers {}
|
||||
|
||||
public readonly onEmitNode: PrintHandlers["onEmitNode"];
|
||||
public readonly onBeforeEmitNodeArray: PrintHandlers["onBeforeEmitNodeArray"];
|
||||
public readonly onAfterEmitNodeArray: PrintHandlers["onAfterEmitNodeArray"];
|
||||
public readonly onBeforeEmitToken: PrintHandlers["onBeforeEmitToken"];
|
||||
public readonly onAfterEmitToken: PrintHandlers["onAfterEmitToken"];
|
||||
function createWriter(newLine: string, omitTrailingSemicolon?: boolean): TextChangesWriter {
|
||||
let lastNonTriviaPosition = 0;
|
||||
|
||||
constructor(newLine: string) {
|
||||
this.writer = createTextWriter(newLine);
|
||||
this.onEmitNode = (hint, node, printCallback) => {
|
||||
if (node) {
|
||||
setPos(node, this.lastNonTriviaPosition);
|
||||
}
|
||||
printCallback(hint, node);
|
||||
if (node) {
|
||||
setEnd(node, this.lastNonTriviaPosition);
|
||||
}
|
||||
};
|
||||
this.onBeforeEmitNodeArray = nodes => {
|
||||
if (nodes) {
|
||||
setPos(nodes, this.lastNonTriviaPosition);
|
||||
}
|
||||
};
|
||||
this.onAfterEmitNodeArray = nodes => {
|
||||
if (nodes) {
|
||||
setEnd(nodes, this.lastNonTriviaPosition);
|
||||
}
|
||||
};
|
||||
this.onBeforeEmitToken = node => {
|
||||
if (node) {
|
||||
setPos(node, this.lastNonTriviaPosition);
|
||||
}
|
||||
};
|
||||
this.onAfterEmitToken = node => {
|
||||
if (node) {
|
||||
setEnd(node, this.lastNonTriviaPosition);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private setLastNonTriviaPosition(s: string, force: boolean) {
|
||||
const writer = omitTrailingSemicolon ? getTrailingSemicolonOmittingWriter(createTextWriter(newLine)) : createTextWriter(newLine);
|
||||
const onEmitNode: PrintHandlers["onEmitNode"] = (hint, node, printCallback) => {
|
||||
if (node) {
|
||||
setPos(node, lastNonTriviaPosition);
|
||||
}
|
||||
printCallback(hint, node);
|
||||
if (node) {
|
||||
setEnd(node, lastNonTriviaPosition);
|
||||
}
|
||||
};
|
||||
const onBeforeEmitNodeArray: PrintHandlers["onBeforeEmitNodeArray"] = nodes => {
|
||||
if (nodes) {
|
||||
setPos(nodes, lastNonTriviaPosition);
|
||||
}
|
||||
};
|
||||
const onAfterEmitNodeArray: PrintHandlers["onAfterEmitNodeArray"] = nodes => {
|
||||
if (nodes) {
|
||||
setEnd(nodes, lastNonTriviaPosition);
|
||||
}
|
||||
};
|
||||
const onBeforeEmitToken: PrintHandlers["onBeforeEmitToken"] = node => {
|
||||
if (node) {
|
||||
setPos(node, lastNonTriviaPosition);
|
||||
}
|
||||
};
|
||||
const onAfterEmitToken: PrintHandlers["onAfterEmitToken"] = node => {
|
||||
if (node) {
|
||||
setEnd(node, lastNonTriviaPosition);
|
||||
}
|
||||
};
|
||||
|
||||
function setLastNonTriviaPosition(s: string, force: boolean) {
|
||||
if (force || !isTrivia(s)) {
|
||||
this.lastNonTriviaPosition = this.writer.getTextPos();
|
||||
lastNonTriviaPosition = writer.getTextPos();
|
||||
let i = 0;
|
||||
while (isWhiteSpaceLike(s.charCodeAt(s.length - i - 1))) {
|
||||
i++;
|
||||
}
|
||||
// trim trailing whitespaces
|
||||
this.lastNonTriviaPosition -= i;
|
||||
lastNonTriviaPosition -= i;
|
||||
}
|
||||
}
|
||||
|
||||
write(s: string): void {
|
||||
this.writer.write(s);
|
||||
this.setLastNonTriviaPosition(s, /*force*/ false);
|
||||
function write(s: string): void {
|
||||
writer.write(s);
|
||||
setLastNonTriviaPosition(s, /*force*/ false);
|
||||
}
|
||||
writeComment(s: string): void {
|
||||
this.writer.writeComment(s);
|
||||
function writeComment(s: string): void {
|
||||
writer.writeComment(s);
|
||||
}
|
||||
writeKeyword(s: string): void {
|
||||
this.writer.writeKeyword(s);
|
||||
this.setLastNonTriviaPosition(s, /*force*/ false);
|
||||
function writeKeyword(s: string): void {
|
||||
writer.writeKeyword(s);
|
||||
setLastNonTriviaPosition(s, /*force*/ false);
|
||||
}
|
||||
writeOperator(s: string): void {
|
||||
this.writer.writeOperator(s);
|
||||
this.setLastNonTriviaPosition(s, /*force*/ false);
|
||||
function writeOperator(s: string): void {
|
||||
writer.writeOperator(s);
|
||||
setLastNonTriviaPosition(s, /*force*/ false);
|
||||
}
|
||||
writePunctuation(s: string): void {
|
||||
this.writer.writePunctuation(s);
|
||||
this.setLastNonTriviaPosition(s, /*force*/ false);
|
||||
function writePunctuation(s: string): void {
|
||||
writer.writePunctuation(s);
|
||||
setLastNonTriviaPosition(s, /*force*/ false);
|
||||
}
|
||||
writeTrailingSemicolon(s: string): void {
|
||||
this.writer.writeTrailingSemicolon(s);
|
||||
this.setLastNonTriviaPosition(s, /*force*/ false);
|
||||
function writeTrailingSemicolon(s: string): void {
|
||||
writer.writeTrailingSemicolon(s);
|
||||
setLastNonTriviaPosition(s, /*force*/ false);
|
||||
}
|
||||
writeParameter(s: string): void {
|
||||
this.writer.writeParameter(s);
|
||||
this.setLastNonTriviaPosition(s, /*force*/ false);
|
||||
function writeParameter(s: string): void {
|
||||
writer.writeParameter(s);
|
||||
setLastNonTriviaPosition(s, /*force*/ false);
|
||||
}
|
||||
writeProperty(s: string): void {
|
||||
this.writer.writeProperty(s);
|
||||
this.setLastNonTriviaPosition(s, /*force*/ false);
|
||||
function writeProperty(s: string): void {
|
||||
writer.writeProperty(s);
|
||||
setLastNonTriviaPosition(s, /*force*/ false);
|
||||
}
|
||||
writeSpace(s: string): void {
|
||||
this.writer.writeSpace(s);
|
||||
this.setLastNonTriviaPosition(s, /*force*/ false);
|
||||
function writeSpace(s: string): void {
|
||||
writer.writeSpace(s);
|
||||
setLastNonTriviaPosition(s, /*force*/ false);
|
||||
}
|
||||
writeStringLiteral(s: string): void {
|
||||
this.writer.writeStringLiteral(s);
|
||||
this.setLastNonTriviaPosition(s, /*force*/ false);
|
||||
function writeStringLiteral(s: string): void {
|
||||
writer.writeStringLiteral(s);
|
||||
setLastNonTriviaPosition(s, /*force*/ false);
|
||||
}
|
||||
writeSymbol(s: string, sym: Symbol): void {
|
||||
this.writer.writeSymbol(s, sym);
|
||||
this.setLastNonTriviaPosition(s, /*force*/ false);
|
||||
function writeSymbol(s: string, sym: Symbol): void {
|
||||
writer.writeSymbol(s, sym);
|
||||
setLastNonTriviaPosition(s, /*force*/ false);
|
||||
}
|
||||
writeLine(): void {
|
||||
this.writer.writeLine();
|
||||
function writeLine(): void {
|
||||
writer.writeLine();
|
||||
}
|
||||
increaseIndent(): void {
|
||||
this.writer.increaseIndent();
|
||||
function increaseIndent(): void {
|
||||
writer.increaseIndent();
|
||||
}
|
||||
decreaseIndent(): void {
|
||||
this.writer.decreaseIndent();
|
||||
function decreaseIndent(): void {
|
||||
writer.decreaseIndent();
|
||||
}
|
||||
getText(): string {
|
||||
return this.writer.getText();
|
||||
function getText(): string {
|
||||
return writer.getText();
|
||||
}
|
||||
rawWrite(s: string): void {
|
||||
this.writer.rawWrite(s);
|
||||
this.setLastNonTriviaPosition(s, /*force*/ false);
|
||||
function rawWrite(s: string): void {
|
||||
writer.rawWrite(s);
|
||||
setLastNonTriviaPosition(s, /*force*/ false);
|
||||
}
|
||||
writeLiteral(s: string): void {
|
||||
this.writer.writeLiteral(s);
|
||||
this.setLastNonTriviaPosition(s, /*force*/ true);
|
||||
function writeLiteral(s: string): void {
|
||||
writer.writeLiteral(s);
|
||||
setLastNonTriviaPosition(s, /*force*/ true);
|
||||
}
|
||||
getTextPos(): number {
|
||||
return this.writer.getTextPos();
|
||||
function getTextPos(): number {
|
||||
return writer.getTextPos();
|
||||
}
|
||||
getLine(): number {
|
||||
return this.writer.getLine();
|
||||
function getLine(): number {
|
||||
return writer.getLine();
|
||||
}
|
||||
getColumn(): number {
|
||||
return this.writer.getColumn();
|
||||
function getColumn(): number {
|
||||
return writer.getColumn();
|
||||
}
|
||||
getIndent(): number {
|
||||
return this.writer.getIndent();
|
||||
function getIndent(): number {
|
||||
return writer.getIndent();
|
||||
}
|
||||
isAtStartOfLine(): boolean {
|
||||
return this.writer.isAtStartOfLine();
|
||||
function isAtStartOfLine(): boolean {
|
||||
return writer.isAtStartOfLine();
|
||||
}
|
||||
clear(): void {
|
||||
this.writer.clear();
|
||||
this.lastNonTriviaPosition = 0;
|
||||
function clear(): void {
|
||||
writer.clear();
|
||||
lastNonTriviaPosition = 0;
|
||||
}
|
||||
|
||||
return {
|
||||
onEmitNode,
|
||||
onBeforeEmitNodeArray,
|
||||
onAfterEmitNodeArray,
|
||||
onBeforeEmitToken,
|
||||
onAfterEmitToken,
|
||||
write,
|
||||
writeComment,
|
||||
writeKeyword,
|
||||
writeOperator,
|
||||
writePunctuation,
|
||||
writeTrailingSemicolon,
|
||||
writeParameter,
|
||||
writeProperty,
|
||||
writeSpace,
|
||||
writeStringLiteral,
|
||||
writeSymbol,
|
||||
writeLine,
|
||||
increaseIndent,
|
||||
decreaseIndent,
|
||||
getText,
|
||||
rawWrite,
|
||||
writeLiteral,
|
||||
getTextPos,
|
||||
getLine,
|
||||
getColumn,
|
||||
getIndent,
|
||||
isAtStartOfLine,
|
||||
clear
|
||||
};
|
||||
}
|
||||
|
||||
function getInsertionPositionAtSourceFileTop(sourceFile: SourceFile): number {
|
||||
|
||||
@@ -1991,4 +1991,51 @@ namespace ts {
|
||||
});
|
||||
return typeIsAccessible ? res : undefined;
|
||||
}
|
||||
|
||||
export function syntaxUsuallyHasTrailingSemicolon(kind: SyntaxKind) {
|
||||
return kind === SyntaxKind.VariableStatement
|
||||
|| kind === SyntaxKind.ExpressionStatement
|
||||
|| kind === SyntaxKind.DoStatement
|
||||
|| kind === SyntaxKind.ContinueStatement
|
||||
|| kind === SyntaxKind.BreakStatement
|
||||
|| kind === SyntaxKind.ReturnStatement
|
||||
|| kind === SyntaxKind.ThrowStatement
|
||||
|| kind === SyntaxKind.DebuggerStatement
|
||||
|| kind === SyntaxKind.PropertyDeclaration
|
||||
|| kind === SyntaxKind.TypeAliasDeclaration
|
||||
|| kind === SyntaxKind.ImportDeclaration
|
||||
|| kind === SyntaxKind.ImportEqualsDeclaration
|
||||
|| kind === SyntaxKind.ExportDeclaration;
|
||||
}
|
||||
|
||||
export function probablyUsesSemicolons(sourceFile: SourceFile): boolean {
|
||||
let withSemicolon = 0;
|
||||
let withoutSemicolon = 0;
|
||||
const nStatementsToObserve = 5;
|
||||
forEachChild(sourceFile, function visit(node): boolean | undefined {
|
||||
if (syntaxUsuallyHasTrailingSemicolon(node.kind)) {
|
||||
const lastToken = node.getLastToken(sourceFile);
|
||||
if (lastToken && lastToken.kind === SyntaxKind.SemicolonToken) {
|
||||
withSemicolon++;
|
||||
}
|
||||
else {
|
||||
withoutSemicolon++;
|
||||
}
|
||||
}
|
||||
if (withSemicolon + withoutSemicolon >= nStatementsToObserve) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return forEachChild(node, visit);
|
||||
});
|
||||
|
||||
// One statement missing a semicolon isn’t sufficient evidence to say the user
|
||||
// doesn’t want semicolons, because they may not even be done writing that statement.
|
||||
if (withSemicolon === 0 && withoutSemicolon <= 1) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// If even 2/5 places have a semicolon, the user probably wants semicolons
|
||||
return withSemicolon / withoutSemicolon > 1 / nStatementsToObserve;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,25 +14,25 @@
|
||||
goTo.marker("0");
|
||||
const preferences: FourSlashInterface.UserPreferences = { includeCompletionsForModuleExports: true };
|
||||
verify.completions(
|
||||
{
|
||||
{
|
||||
marker: "0",
|
||||
exact: [
|
||||
completion.globalThisEntry,
|
||||
completion.undefinedVarEntry,
|
||||
...completion.statementKeywordsWithTypes
|
||||
],
|
||||
preferences
|
||||
completion.globalThisEntry,
|
||||
completion.undefinedVarEntry,
|
||||
...completion.statementKeywordsWithTypes
|
||||
],
|
||||
preferences
|
||||
},
|
||||
{
|
||||
marker: "1",
|
||||
includes: {
|
||||
name: "fooBar",
|
||||
source: "/src/foo-bar",
|
||||
sourceDisplay: "./foo-bar",
|
||||
text: "(property) default: 0",
|
||||
kind: "property",
|
||||
hasAction: true,
|
||||
sortText: completion.SortText.AutoImportSuggestions
|
||||
name: "fooBar",
|
||||
source: "/src/foo-bar",
|
||||
sourceDisplay: "./foo-bar",
|
||||
text: "(property) default: 0",
|
||||
kind: "property",
|
||||
hasAction: true,
|
||||
sortText: completion.SortText.AutoImportSuggestions
|
||||
},
|
||||
preferences,
|
||||
},
|
||||
@@ -41,7 +41,7 @@ verify.applyCodeActionFromCompletion("1", {
|
||||
name: "fooBar",
|
||||
source: "/src/foo-bar",
|
||||
description: `Import default 'fooBar' from module "./foo-bar"`,
|
||||
newFileContent: `import fooBar from "./foo-bar";
|
||||
newFileContent: `import fooBar from "./foo-bar"
|
||||
|
||||
def
|
||||
fooB`,
|
||||
|
||||
@@ -38,7 +38,7 @@ verify.applyCodeActionFromCompletion("0", {
|
||||
name: "fooBar",
|
||||
source: "/src/foo-bar",
|
||||
description: `Import 'fooBar' from module "./foo-bar"`,
|
||||
newFileContent: `import fooBar = require("./foo-bar");
|
||||
newFileContent: `import fooBar = require("./foo-bar")
|
||||
|
||||
exp
|
||||
fooB`,
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
/// <reference path="fourslash.ts" />
|
||||
|
||||
// @Filename: /a.ts
|
||||
////export function foo() {}
|
||||
|
||||
// @Filename: /b.ts
|
||||
////const x = 0
|
||||
////const y = 1
|
||||
////const z = fo/**/
|
||||
|
||||
verify.applyCodeActionFromCompletion("", {
|
||||
name: "foo",
|
||||
source: "/a",
|
||||
description: `Import 'foo' from module "./a"`,
|
||||
newFileContent: `import { foo } from "./a"
|
||||
|
||||
const x = 0
|
||||
const y = 1
|
||||
const z = fo`,
|
||||
});
|
||||
@@ -1,7 +1,7 @@
|
||||
/// <reference path='fourslash.ts' />
|
||||
|
||||
////export default function() {
|
||||
//// /*start*/0/*end*/
|
||||
//// /*start*/0/*end*/;
|
||||
////}
|
||||
|
||||
goTo.select('start', 'end')
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/// <reference path='fourslash.ts' />
|
||||
|
||||
//// function foo(a: number, b?: number, ...c: number[]): boolean {
|
||||
//// return false as /*a*/boolean/*b*/
|
||||
//// return false as /*a*/boolean/*b*/;
|
||||
//// }
|
||||
|
||||
goTo.select("a", "b");
|
||||
@@ -12,6 +12,6 @@ edit.applyRefactor({
|
||||
newContent: `function foo(a: number, b?: number, ...c: number[]): boolean {
|
||||
type /*RENAME*/NewType = boolean;
|
||||
|
||||
return false as NewType
|
||||
return false as NewType;
|
||||
}`,
|
||||
});
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/// <reference path='fourslash.ts' />
|
||||
|
||||
//// type A<T = /*a*/boolean/*b*/> = string | number | T
|
||||
//// type A<T = /*a*/boolean/*b*/> = string | number | T;
|
||||
|
||||
goTo.select("a", "b");
|
||||
edit.applyRefactor({
|
||||
@@ -9,5 +9,5 @@ edit.applyRefactor({
|
||||
actionDescription: "Extract to type alias",
|
||||
newContent: `type /*RENAME*/NewType = boolean;
|
||||
|
||||
type A<T = NewType> = string | number | T`,
|
||||
type A<T = NewType> = string | number | T;`,
|
||||
});
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/// <reference path='fourslash.ts' />
|
||||
|
||||
//// type A<T = boolean> = /*a*/string/*b*/ | number | T
|
||||
//// type A<T = boolean> = /*a*/string/*b*/ | number | T;
|
||||
|
||||
goTo.select("a", "b");
|
||||
edit.applyRefactor({
|
||||
@@ -9,5 +9,5 @@ edit.applyRefactor({
|
||||
actionDescription: "Extract to type alias",
|
||||
newContent: `type /*RENAME*/NewType = string;
|
||||
|
||||
type A<T = boolean> = NewType | number | T`,
|
||||
type A<T = boolean> = NewType | number | T;`,
|
||||
});
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/// <reference path='fourslash.ts' />
|
||||
|
||||
//// type A<T = boolean> = string | number | /*a*/T/*b*/
|
||||
//// type A<T = boolean> = string | number | /*a*/T/*b*/;
|
||||
|
||||
goTo.select("a", "b");
|
||||
edit.applyRefactor({
|
||||
@@ -9,5 +9,5 @@ edit.applyRefactor({
|
||||
actionDescription: "Extract to type alias",
|
||||
newContent: `type /*RENAME*/NewType<T> = T;
|
||||
|
||||
type A<T = boolean> = string | number | NewType<T>`,
|
||||
type A<T = boolean> = string | number | NewType<T>;`,
|
||||
});
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/// <reference path='fourslash.ts' />
|
||||
|
||||
//// type A<B, C, D = B> = /*a*/Partial<C | string>/*b*/ & D | C
|
||||
//// type A<B, C, D = B> = /*a*/Partial<C | string>/*b*/ & D | C;
|
||||
|
||||
goTo.select("a", "b");
|
||||
edit.applyRefactor({
|
||||
@@ -9,6 +9,6 @@ edit.applyRefactor({
|
||||
actionDescription: "Extract to type alias",
|
||||
newContent: `type /*RENAME*/NewType<C> = Partial<C | string>;
|
||||
|
||||
type A<B, C, D = B> = NewType<C> & D | C`,
|
||||
type A<B, C, D = B> = NewType<C> & D | C;`,
|
||||
});
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/// <reference path='fourslash.ts' />
|
||||
|
||||
//// type A<B, C, D = B> = /*a*/Partial<C | string | D>/*b*/ & D | C
|
||||
//// type A<B, C, D = B> = /*a*/Partial<C | string | D>/*b*/ & D | C;
|
||||
|
||||
goTo.select("a", "b");
|
||||
edit.applyRefactor({
|
||||
@@ -9,6 +9,6 @@ edit.applyRefactor({
|
||||
actionDescription: "Extract to type alias",
|
||||
newContent: `type /*RENAME*/NewType<C, D> = Partial<C | string | D>;
|
||||
|
||||
type A<B, C, D = B> = NewType<C, D> & D | C`,
|
||||
type A<B, C, D = B> = NewType<C, D> & D | C;`,
|
||||
});
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/// <reference path='fourslash.ts' />
|
||||
|
||||
//// type A<T, U> = () => <T>(v: /*a*/T/*b*/) => (v: T) => <T>(v: T) => U
|
||||
//// type A<T, U> = () => <T>(v: /*a*/T/*b*/) => (v: T) => <T>(v: T) => U;
|
||||
|
||||
goTo.select("a", "b");
|
||||
edit.applyRefactor({
|
||||
@@ -9,5 +9,5 @@ edit.applyRefactor({
|
||||
actionDescription: "Extract to type alias",
|
||||
newContent: `type /*RENAME*/NewType<T> = T;
|
||||
|
||||
type A<T, U> = () => <T>(v: NewType<T>) => (v: T) => <T>(v: T) => U`,
|
||||
type A<T, U> = () => <T>(v: NewType<T>) => (v: T) => <T>(v: T) => U;`,
|
||||
});
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/// <reference path='fourslash.ts' />
|
||||
|
||||
//// type A<T, U> = () => <T>(v: T) => (v: /*a*/T/*b*/) => <T>(v: T) => U
|
||||
//// type A<T, U> = () => <T>(v: T) => (v: /*a*/T/*b*/) => <T>(v: T) => U;
|
||||
|
||||
goTo.select("a", "b");
|
||||
edit.applyRefactor({
|
||||
@@ -9,5 +9,5 @@ edit.applyRefactor({
|
||||
actionDescription: "Extract to type alias",
|
||||
newContent: `type /*RENAME*/NewType<T> = T;
|
||||
|
||||
type A<T, U> = () => <T>(v: T) => (v: NewType<T>) => <T>(v: T) => U`,
|
||||
type A<T, U> = () => <T>(v: T) => (v: NewType<T>) => <T>(v: T) => U;`,
|
||||
});
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/// <reference path='fourslash.ts' />
|
||||
|
||||
//// type A<T, U> = () => <T>(v: T) => (v: T) => <T>(v: /*a*/T/*b*/) => U
|
||||
//// type A<T, U> = () => <T>(v: T) => (v: T) => <T>(v: /*a*/T/*b*/) => U;
|
||||
|
||||
goTo.select("a", "b");
|
||||
edit.applyRefactor({
|
||||
@@ -9,5 +9,5 @@ edit.applyRefactor({
|
||||
actionDescription: "Extract to type alias",
|
||||
newContent: `type /*RENAME*/NewType<T> = T;
|
||||
|
||||
type A<T, U> = () => <T>(v: T) => (v: T) => <T>(v: NewType<T>) => U`,
|
||||
type A<T, U> = () => <T>(v: T) => (v: T) => <T>(v: NewType<T>) => U;`,
|
||||
});
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/// <reference path='fourslash.ts' />
|
||||
|
||||
//// type A<T, U> = () => <T>(v: T) => (v: T) => <T>(v: T) => /*a*/U/*b*/
|
||||
//// type A<T, U> = () => <T>(v: T) => (v: T) => <T>(v: T) => /*a*/U/*b*/;
|
||||
|
||||
goTo.select("a", "b");
|
||||
edit.applyRefactor({
|
||||
@@ -9,5 +9,5 @@ edit.applyRefactor({
|
||||
actionDescription: "Extract to type alias",
|
||||
newContent: `type /*RENAME*/NewType<U> = U;
|
||||
|
||||
type A<T, U> = () => <T>(v: T) => (v: T) => <T>(v: T) => NewType<U>`,
|
||||
type A<T, U> = () => <T>(v: T) => (v: T) => <T>(v: T) => NewType<U>;`,
|
||||
});
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/// <reference path='fourslash.ts' />
|
||||
|
||||
//// type A<T, U> = () => <T>(v: T) => (v: T) => /*a*/<T>(v: T) => U/*b*/
|
||||
//// type A<T, U> = () => <T>(v: T) => (v: T) => /*a*/<T>(v: T) => U/*b*/;
|
||||
|
||||
goTo.select("a", "b");
|
||||
edit.applyRefactor({
|
||||
@@ -9,5 +9,5 @@ edit.applyRefactor({
|
||||
actionDescription: "Extract to type alias",
|
||||
newContent: `type /*RENAME*/NewType<U> = <T>(v: T) => U;
|
||||
|
||||
type A<T, U> = () => <T>(v: T) => (v: T) => NewType<U>`,
|
||||
type A<T, U> = () => <T>(v: T) => (v: T) => NewType<U>;`,
|
||||
});
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/// <reference path='fourslash.ts' />
|
||||
|
||||
//// type A<T, U> = () => <T>(v: T) => /*a*/(v: T) => <T>(v: T) => U/*b*/
|
||||
//// type A<T, U> = () => <T>(v: T) => /*a*/(v: T) => <T>(v: T) => U/*b*/;
|
||||
|
||||
goTo.select("a", "b");
|
||||
edit.applyRefactor({
|
||||
@@ -9,5 +9,5 @@ edit.applyRefactor({
|
||||
actionDescription: "Extract to type alias",
|
||||
newContent: `type /*RENAME*/NewType<T, U> = (v: T) => <T>(v: T) => U;
|
||||
|
||||
type A<T, U> = () => <T>(v: T) => NewType<T, U>`,
|
||||
type A<T, U> = () => <T>(v: T) => NewType<T, U>;`,
|
||||
});
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/// <reference path='fourslash.ts' />
|
||||
|
||||
//// type A<T, U> = () => /*a*/<T>(v: T) => (v: T) => <T>(v: T) => U/*b*/
|
||||
//// type A<T, U> = () => /*a*/<T>(v: T) => (v: T) => <T>(v: T) => U/*b*/;
|
||||
|
||||
goTo.select("a", "b");
|
||||
edit.applyRefactor({
|
||||
@@ -9,5 +9,5 @@ edit.applyRefactor({
|
||||
actionDescription: "Extract to type alias",
|
||||
newContent: `type /*RENAME*/NewType<U> = <T>(v: T) => (v: T) => <T>(v: T) => U;
|
||||
|
||||
type A<T, U> = () => NewType<U>`,
|
||||
type A<T, U> = () => NewType<U>;`,
|
||||
});
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/// <reference path='fourslash.ts' />
|
||||
|
||||
//// type A<T, U> = /*a*/() => <T>(v: T) => (v: T) => <T>(v: T) => U/*b*/
|
||||
//// type A<T, U> = /*a*/() => <T>(v: T) => (v: T) => <T>(v: T) => U/*b*/;
|
||||
|
||||
goTo.select("a", "b");
|
||||
edit.applyRefactor({
|
||||
@@ -9,5 +9,5 @@ edit.applyRefactor({
|
||||
actionDescription: "Extract to type alias",
|
||||
newContent: `type /*RENAME*/NewType<U> = () => <T>(v: T) => (v: T) => <T>(v: T) => U;
|
||||
|
||||
type A<T, U> = NewType<U>`,
|
||||
type A<T, U> = NewType<U>;`,
|
||||
});
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/// <reference path='fourslash.ts' />
|
||||
|
||||
//// type Item<T> = /*a*/T/*b*/ extends (infer P)[] ? P : never
|
||||
//// type Item<T> = /*a*/T/*b*/ extends (infer P)[] ? P : never;
|
||||
|
||||
goTo.select("a", "b");
|
||||
edit.applyRefactor({
|
||||
@@ -9,5 +9,5 @@ edit.applyRefactor({
|
||||
actionDescription: "Extract to type alias",
|
||||
newContent: `type /*RENAME*/NewType<T> = T;
|
||||
|
||||
type Item<T> = NewType<T> extends (infer P)[] ? P : never`,
|
||||
type Item<T> = NewType<T> extends (infer P)[] ? P : never;`,
|
||||
});
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/// <reference path='fourslash.ts' />
|
||||
|
||||
//// type Item<T> = T extends (infer P)[] ? /*a*/P/*b*/ : never
|
||||
//// type Item<T> = T extends (infer P)[] ? /*a*/P/*b*/ : never;
|
||||
|
||||
goTo.select("a", "b");
|
||||
edit.applyRefactor({
|
||||
@@ -9,5 +9,5 @@ edit.applyRefactor({
|
||||
actionDescription: "Extract to type alias",
|
||||
newContent: `type /*RENAME*/NewType<P> = P;
|
||||
|
||||
type Item<T> = T extends (infer P)[] ? NewType<P> : never`,
|
||||
type Item<T> = T extends (infer P)[] ? NewType<P> : never;`,
|
||||
});
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/// <reference path='fourslash.ts' />
|
||||
|
||||
//// type Item<T> = T extends (infer P)[] ? P : /*a*/never/*b*/
|
||||
//// type Item<T> = T extends (infer P)[] ? P : /*a*/never/*b*/;
|
||||
|
||||
goTo.select("a", "b");
|
||||
edit.applyRefactor({
|
||||
@@ -9,5 +9,5 @@ edit.applyRefactor({
|
||||
actionDescription: "Extract to type alias",
|
||||
newContent: `type /*RENAME*/NewType = never;
|
||||
|
||||
type Item<T> = T extends (infer P)[] ? P : NewType`,
|
||||
type Item<T> = T extends (infer P)[] ? P : NewType;`,
|
||||
});
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/// <reference path='fourslash.ts' />
|
||||
|
||||
//// type Item<T> = /*a*/T extends (infer P)[] ? P : never/*b*/
|
||||
//// type Item<T> = /*a*/T extends (infer P)[] ? P : never/*b*/;
|
||||
|
||||
goTo.select("a", "b");
|
||||
edit.applyRefactor({
|
||||
@@ -9,5 +9,5 @@ edit.applyRefactor({
|
||||
actionDescription: "Extract to type alias",
|
||||
newContent: `type /*RENAME*/NewType<T> = T extends (infer P)[] ? P : never;
|
||||
|
||||
type Item<T> = NewType<T>`,
|
||||
type Item<T> = NewType<T>;`,
|
||||
});
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/// <reference path='fourslash.ts' />
|
||||
|
||||
//// type Union<T, U> = /*a*/U | T/*b*/
|
||||
//// type Union<T, U> = /*a*/U | T/*b*/;
|
||||
|
||||
goTo.select("a", "b");
|
||||
edit.applyRefactor({
|
||||
@@ -9,5 +9,5 @@ edit.applyRefactor({
|
||||
actionDescription: "Extract to type alias",
|
||||
newContent: `type /*RENAME*/NewType<U, T> = U | T;
|
||||
|
||||
type Union<T, U> = NewType<U, T>`,
|
||||
type Union<T, U> = NewType<U, T>;`,
|
||||
});
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/// <reference path='fourslash.ts' />
|
||||
|
||||
//// type A = (v: /*a*/string | number/*b*/) => v is string
|
||||
//// type A = (v: /*a*/string | number/*b*/) => v is string;
|
||||
|
||||
goTo.select("a", "b");
|
||||
edit.applyRefactor({
|
||||
@@ -9,6 +9,6 @@ edit.applyRefactor({
|
||||
actionDescription: "Extract to type alias",
|
||||
newContent: `type /*RENAME*/NewType = string | number;
|
||||
|
||||
type A = (v: NewType) => v is string`,
|
||||
type A = (v: NewType) => v is string;`,
|
||||
});
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/// <reference path='fourslash.ts' />
|
||||
|
||||
//// type A = (v: string | number) => v is /*a*/string/*b*/
|
||||
//// type A = (v: string | number) => v is /*a*/string/*b*/;
|
||||
|
||||
goTo.select("a", "b");
|
||||
edit.applyRefactor({
|
||||
@@ -9,5 +9,5 @@ edit.applyRefactor({
|
||||
actionDescription: "Extract to type alias",
|
||||
newContent: `type /*RENAME*/NewType = string;
|
||||
|
||||
type A = (v: string | number) => v is NewType`,
|
||||
type A = (v: string | number) => v is NewType;`,
|
||||
});
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/// <reference path='fourslash.ts' />
|
||||
|
||||
//// type A = /*a*/(v: string | number) => v is string/*b*/
|
||||
//// type A = /*a*/(v: string | number) => v is string/*b*/;
|
||||
|
||||
goTo.select("a", "b");
|
||||
edit.applyRefactor({
|
||||
@@ -9,5 +9,5 @@ edit.applyRefactor({
|
||||
actionDescription: "Extract to type alias",
|
||||
newContent: `type /*RENAME*/NewType = (v: string | number) => v is string;
|
||||
|
||||
type A = NewType`,
|
||||
type A = NewType;`,
|
||||
});
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
/// <reference path='fourslash.ts' />
|
||||
|
||||
//// const a = 1
|
||||
//// type A = (v: string | number) => /*a*/typeof a/*b*/
|
||||
//// const a = 1;
|
||||
//// type A = (v: string | number) => /*a*/typeof a/*b*/;
|
||||
|
||||
goTo.select("a", "b");
|
||||
edit.applyRefactor({
|
||||
refactorName: "Extract type",
|
||||
actionName: "Extract to type alias",
|
||||
actionDescription: "Extract to type alias",
|
||||
newContent: `const a = 1
|
||||
newContent: `const a = 1;
|
||||
type /*RENAME*/NewType = typeof a;
|
||||
|
||||
type A = (v: string | number) => NewType`,
|
||||
type A = (v: string | number) => NewType;`,
|
||||
});
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/// <reference path='fourslash.ts' />
|
||||
|
||||
//// type A<T> = /*a*/B.C.D<T>/*b*/
|
||||
//// type A<T> = /*a*/B.C.D<T>/*b*/;
|
||||
|
||||
goTo.select("a", "b");
|
||||
edit.applyRefactor({
|
||||
@@ -9,5 +9,5 @@ edit.applyRefactor({
|
||||
actionDescription: "Extract to type alias",
|
||||
newContent: `type /*RENAME*/NewType<T> = B.C.D<T>;
|
||||
|
||||
type A<T> = NewType<T>`,
|
||||
type A<T> = NewType<T>;`,
|
||||
});
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/// <reference path='fourslash.ts' />
|
||||
|
||||
//// type A = /*a*/B.C.D/*b*/
|
||||
//// type A = /*a*/B.C.D/*b*/;
|
||||
|
||||
goTo.select("a", "b");
|
||||
edit.applyRefactor({
|
||||
@@ -9,5 +9,5 @@ edit.applyRefactor({
|
||||
actionDescription: "Extract to type alias",
|
||||
newContent: `type /*RENAME*/NewType = B.C.D;
|
||||
|
||||
type A = NewType`,
|
||||
type A = NewType;`,
|
||||
});
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
/// <reference path='fourslash.ts' />
|
||||
|
||||
//// namespace A { export const b = 1 }
|
||||
//// function a(b: string): /*a*/typeof A.b/*b*/ { return 1 }
|
||||
//// namespace A { export const b = 1; }
|
||||
//// function a(b: string): /*a*/typeof A.b/*b*/ { return 1; }
|
||||
|
||||
goTo.select("a", "b");
|
||||
edit.applyRefactor({
|
||||
refactorName: "Extract type",
|
||||
actionName: "Extract to type alias",
|
||||
actionDescription: "Extract to type alias",
|
||||
newContent: `namespace A { export const b = 1 }
|
||||
newContent: `namespace A { export const b = 1; }
|
||||
type /*RENAME*/NewType = typeof A.b;
|
||||
|
||||
function a(b: string): NewType { return 1 }`,
|
||||
function a(b: string): NewType { return 1; }`,
|
||||
});
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
/// <reference path='fourslash.ts' />
|
||||
|
||||
//// type A<T extends string> = T
|
||||
//// type B<T extends string> = /*a*/A<T>/*b*/
|
||||
//// type A<T extends string> = T;
|
||||
//// type B<T extends string> = /*a*/A<T>/*b*/;
|
||||
|
||||
goTo.select("a", "b");
|
||||
edit.applyRefactor({
|
||||
refactorName: "Extract type",
|
||||
actionName: "Extract to type alias",
|
||||
actionDescription: "Extract to type alias",
|
||||
newContent: `type A<T extends string> = T
|
||||
newContent: `type A<T extends string> = T;
|
||||
type /*RENAME*/NewType<T extends string> = A<T>;
|
||||
|
||||
type B<T extends string> = NewType<T>`,
|
||||
type B<T extends string> = NewType<T>;`,
|
||||
});
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/// <reference path='fourslash.ts' />
|
||||
|
||||
//// function foo(a: /*a*/number/*b*/, b?: number, ...c: number[]): boolean {
|
||||
//// return false as boolean
|
||||
//// return false as boolean;
|
||||
//// }
|
||||
|
||||
goTo.select("a", "b");
|
||||
@@ -12,6 +12,6 @@ edit.applyRefactor({
|
||||
newContent: `type /*RENAME*/NewType = number;
|
||||
|
||||
function foo(a: NewType, b?: number, ...c: number[]): boolean {
|
||||
return false as boolean
|
||||
return false as boolean;
|
||||
}`,
|
||||
});
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/// <reference path='fourslash.ts' />
|
||||
|
||||
//// function foo(a: number, b?: /*a*/number/*b*/, ...c: number[]): boolean {
|
||||
//// return false as boolean
|
||||
//// return false as boolean;
|
||||
//// }
|
||||
|
||||
goTo.select("a", "b");
|
||||
@@ -12,6 +12,6 @@ edit.applyRefactor({
|
||||
newContent: `type /*RENAME*/NewType = number;
|
||||
|
||||
function foo(a: number, b?: NewType, ...c: number[]): boolean {
|
||||
return false as boolean
|
||||
return false as boolean;
|
||||
}`,
|
||||
});
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/// <reference path='fourslash.ts' />
|
||||
|
||||
//// function foo(a: number, b?: number, ...c: /*a*/number[]/*b*/): boolean {
|
||||
//// return false as boolean
|
||||
//// return false as boolean;
|
||||
//// }
|
||||
|
||||
goTo.select("a", "b");
|
||||
@@ -12,6 +12,6 @@ edit.applyRefactor({
|
||||
newContent: `type /*RENAME*/NewType = number[];
|
||||
|
||||
function foo(a: number, b?: number, ...c: NewType): boolean {
|
||||
return false as boolean
|
||||
return false as boolean;
|
||||
}`,
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user