mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-04-17 13:48:46 -05:00
Fix(54284) (#54973)
This commit is contained in:
@@ -40,7 +40,6 @@ import {
|
||||
FindAllReferences,
|
||||
findIndex,
|
||||
findLast,
|
||||
findLastIndex,
|
||||
firstDefined,
|
||||
flatMap,
|
||||
forEachKey,
|
||||
@@ -82,7 +81,6 @@ import {
|
||||
isIdentifier,
|
||||
isImportDeclaration,
|
||||
isImportEqualsDeclaration,
|
||||
isNamedDeclaration,
|
||||
isNamedExports,
|
||||
isObjectLiteralExpression,
|
||||
isOmittedExpression,
|
||||
@@ -117,7 +115,6 @@ import {
|
||||
PropertyAccessExpression,
|
||||
PropertyAssignment,
|
||||
QuotePreference,
|
||||
rangeContainsRange,
|
||||
RefactorContext,
|
||||
RefactorEditInfo,
|
||||
RequireOrImportCall,
|
||||
@@ -182,7 +179,7 @@ registerRefactor(refactorNameForMoveToFile, {
|
||||
if (host.fileExists(targetFile) && program.getSourceFile(targetFile) === undefined) {
|
||||
return error(getLocaleSpecificMessage(Diagnostics.Cannot_move_statements_to_the_selected_file));
|
||||
}
|
||||
const edits = textChanges.ChangeTracker.with(context, t => doChange(context, context.file, interactiveRefactorArguments.targetFile, program, statements, t, context.host, context.preferences));
|
||||
const edits = textChanges.ChangeTracker.with(context, t => doChange(context, context.file, interactiveRefactorArguments.targetFile, context.program, statements, t, context.host, context.preferences));
|
||||
return { edits, renameFilename: undefined, renameLocation: undefined };
|
||||
}
|
||||
return error(getLocaleSpecificMessage(Diagnostics.Cannot_move_to_file_selected_file_is_invalid));
|
||||
@@ -196,7 +193,7 @@ function error(notApplicableReason: string) {
|
||||
function doChange(context: RefactorContext, oldFile: SourceFile, targetFile: string, program: Program, toMove: ToMove, changes: textChanges.ChangeTracker, host: LanguageServiceHost, preferences: UserPreferences): void {
|
||||
const checker = program.getTypeChecker();
|
||||
const usage = getUsageInfo(oldFile, toMove.all, checker);
|
||||
// For a new file
|
||||
//For a new file
|
||||
if (!host.fileExists(targetFile)) {
|
||||
changes.createNewFile(oldFile, targetFile, getNewStatementsAndRemoveFromOldFile(oldFile, targetFile, usage, changes, toMove, program, host, preferences));
|
||||
addNewFileToTsconfig(program, changes, oldFile.fileName, targetFile, hostGetCanonicalFileName(host));
|
||||
@@ -913,28 +910,33 @@ function getRangeToMove(context: RefactorContext): RangeToMove | undefined {
|
||||
const range = createTextRangeFromSpan(getRefactorContextSpan(context));
|
||||
const { statements } = file;
|
||||
|
||||
const startNodeIndex = findIndex(statements, s => s.end > range.pos);
|
||||
let startNodeIndex = findIndex(statements, s => s.end > range.pos);
|
||||
if (startNodeIndex === -1) return undefined;
|
||||
|
||||
const startStatement = statements[startNodeIndex];
|
||||
if (isNamedDeclaration(startStatement) && startStatement.name && rangeContainsRange(startStatement.name, range)) {
|
||||
return { toMove: [statements[startNodeIndex]], afterLast: statements[startNodeIndex + 1] };
|
||||
}
|
||||
|
||||
const overloadRangeToMove = getOverloadRangeToMove(file, startStatement);
|
||||
if (overloadRangeToMove) {
|
||||
return overloadRangeToMove;
|
||||
startNodeIndex = overloadRangeToMove.start;
|
||||
}
|
||||
|
||||
// Can't only partially include the start node or be partially into the next node
|
||||
if (range.pos > startStatement.getStart(file)) return undefined;
|
||||
const afterEndNodeIndex = findIndex(statements, s => s.end > range.end, startNodeIndex);
|
||||
// Can't be partially into the next node
|
||||
if (afterEndNodeIndex !== -1 && (afterEndNodeIndex === 0 || statements[afterEndNodeIndex].getStart(file) < range.end)) return undefined;
|
||||
let endNodeIndex = findIndex(statements, s => s.end >= range.end, startNodeIndex);
|
||||
/**
|
||||
* [|const a = 2;
|
||||
* function foo() {
|
||||
* }
|
||||
* |]
|
||||
*/
|
||||
if (endNodeIndex !== -1 && range.end <= statements[endNodeIndex].getStart()) {
|
||||
endNodeIndex--;
|
||||
}
|
||||
const endingOverloadRangeToMove = getOverloadRangeToMove(file, statements[endNodeIndex]);
|
||||
if (endingOverloadRangeToMove) {
|
||||
endNodeIndex = endingOverloadRangeToMove.end;
|
||||
}
|
||||
|
||||
return {
|
||||
toMove: statements.slice(startNodeIndex, afterEndNodeIndex === -1 ? statements.length : afterEndNodeIndex),
|
||||
afterLast: afterEndNodeIndex === -1 ? undefined : statements[afterEndNodeIndex],
|
||||
toMove: statements.slice(startNodeIndex, endNodeIndex === -1 ? statements.length : endNodeIndex + 1),
|
||||
afterLast: endNodeIndex === -1 ? undefined : statements[endNodeIndex + 1]
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1204,10 +1206,12 @@ function getOverloadRangeToMove(sourceFile: SourceFile, statement: Statement) {
|
||||
if (declarations === undefined || length(declarations) <= 1 || !contains(declarations, statement)) {
|
||||
return undefined;
|
||||
}
|
||||
const firstDecl = declarations[0];
|
||||
const lastDecl = declarations[length(declarations) - 1];
|
||||
const statementsToMove = mapDefined(declarations, d => getSourceFileOfNode(d) === sourceFile && isStatement(d) ? d : undefined);
|
||||
const end = findLastIndex(sourceFile.statements, s => s.end > lastDecl.end);
|
||||
return { toMove: statementsToMove, afterLast: end >= 0 ? sourceFile.statements[end] : undefined };
|
||||
const end = findIndex(sourceFile.statements, s => s.end >= lastDecl.end);
|
||||
const start = findIndex(sourceFile.statements, s => s.end >= firstDecl.end);
|
||||
return { toMove: statementsToMove, start, end };
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
21
tests/cases/fourslash/moveToFile_expandSelectionRange1.ts
Normal file
21
tests/cases/fourslash/moveToFile_expandSelectionRange1.ts
Normal file
@@ -0,0 +1,21 @@
|
||||
/// <reference path='fourslash.ts' />
|
||||
|
||||
//@Filename: /bar.ts
|
||||
////
|
||||
|
||||
// @Filename: /a.ts
|
||||
////co[|nst a = 1|]23;
|
||||
////function foo() { }
|
||||
|
||||
verify.moveToFile({
|
||||
newFileContents: {
|
||||
"/a.ts":
|
||||
`function foo() { }`,
|
||||
|
||||
"/bar.ts":
|
||||
`
|
||||
const a = 123;
|
||||
`,
|
||||
},
|
||||
interactiveRefactorArguments: { targetFile: "/bar.ts" }
|
||||
});
|
||||
35
tests/cases/fourslash/moveToFile_expandSelectionRange10.ts
Normal file
35
tests/cases/fourslash/moveToFile_expandSelectionRange10.ts
Normal file
@@ -0,0 +1,35 @@
|
||||
/// <reference path='fourslash.ts' />
|
||||
|
||||
//@Filename: /bar.ts
|
||||
////
|
||||
|
||||
// @Filename: /a.ts
|
||||
////const b = 2;[|
|
||||
////const a = 1;
|
||||
////function add(x: number, y: number): number;
|
||||
////function add(x: string, y: string): string;
|
||||
////function add(x: any, y: any) {
|
||||
//// return x + y;
|
||||
////}
|
||||
////|]
|
||||
////const c = 3;
|
||||
|
||||
|
||||
verify.moveToFile({
|
||||
newFileContents: {
|
||||
"/a.ts":
|
||||
`const b = 2;
|
||||
const c = 3;`,
|
||||
|
||||
"/bar.ts":
|
||||
`
|
||||
const a = 1;
|
||||
function add(x: number, y: number): number;
|
||||
function add(x: string, y: string): string;
|
||||
function add(x: any, y: any) {
|
||||
return x + y;
|
||||
}
|
||||
`,
|
||||
},
|
||||
interactiveRefactorArguments: { targetFile: "/bar.ts" }
|
||||
});
|
||||
34
tests/cases/fourslash/moveToFile_expandSelectionRange11.ts
Normal file
34
tests/cases/fourslash/moveToFile_expandSelectionRange11.ts
Normal file
@@ -0,0 +1,34 @@
|
||||
/// <reference path='fourslash.ts' />
|
||||
|
||||
//@Filename: /bar.ts
|
||||
////const b = 2;
|
||||
|
||||
// @Filename: /a.ts
|
||||
////const a = 1;
|
||||
////function[| add(x: number, y: number): number;
|
||||
////function add(x: string, y: string): string;
|
||||
////function add(x: any, y: any) {
|
||||
//// return x + y;
|
||||
////}
|
||||
////
|
||||
//// |]const b = 2;
|
||||
////const c = 3;
|
||||
|
||||
verify.moveToFile({
|
||||
newFileContents: {
|
||||
"/a.ts":
|
||||
`const a = 1;
|
||||
const b = 2;
|
||||
const c = 3;`,
|
||||
|
||||
"/bar.ts":
|
||||
`const b = 2;
|
||||
function add(x: number, y: number): number;
|
||||
function add(x: string, y: string): string;
|
||||
function add(x: any, y: any) {
|
||||
return x + y;
|
||||
}
|
||||
`,
|
||||
},
|
||||
interactiveRefactorArguments: { targetFile: "/bar.ts" }
|
||||
});
|
||||
34
tests/cases/fourslash/moveToFile_expandSelectionRange12.ts
Normal file
34
tests/cases/fourslash/moveToFile_expandSelectionRange12.ts
Normal file
@@ -0,0 +1,34 @@
|
||||
/// <reference path='fourslash.ts' />
|
||||
|
||||
//@Filename: /bar.ts
|
||||
////const b = 2;
|
||||
|
||||
// @Filename: /a.ts
|
||||
////const a = 1;[|
|
||||
////function add(x: number, y: number): number;
|
||||
////function add(x: string, y: string): string;
|
||||
////function add(x: any, y: any) {
|
||||
//// return x + y;
|
||||
////}
|
||||
////function foo() {}
|
||||
////|]
|
||||
|
||||
|
||||
verify.moveToFile({
|
||||
newFileContents: {
|
||||
"/a.ts":
|
||||
`const a = 1;
|
||||
`,
|
||||
|
||||
"/bar.ts":
|
||||
`const b = 2;
|
||||
function add(x: number, y: number): number;
|
||||
function add(x: string, y: string): string;
|
||||
function add(x: any, y: any) {
|
||||
return x + y;
|
||||
}
|
||||
function foo() { }
|
||||
`,
|
||||
},
|
||||
interactiveRefactorArguments: { targetFile: "/bar.ts" }
|
||||
});
|
||||
43
tests/cases/fourslash/moveToFile_expandSelectionRange13.ts
Normal file
43
tests/cases/fourslash/moveToFile_expandSelectionRange13.ts
Normal file
@@ -0,0 +1,43 @@
|
||||
/// <reference path='fourslash.ts' />
|
||||
|
||||
//@Filename: /bar.ts
|
||||
////const b = 2;
|
||||
|
||||
// @Filename: /a.ts
|
||||
////const a = 1;
|
||||
////function add1(x: number, y: number): number;
|
||||
////functi[|on add1(x: string, y: string): string;
|
||||
////function add1(x: any, y: any) {
|
||||
//// return x + y;
|
||||
////}
|
||||
////function foo() {}
|
||||
////function add2(x: number, y: number): number;
|
||||
////function add2(x: string, y: string): string;
|
||||
////function add2(x: any, y: any) {
|
||||
//// return x + y;
|
||||
////}|]
|
||||
////const c = 3;
|
||||
|
||||
verify.moveToFile({
|
||||
newFileContents: {
|
||||
"/a.ts":
|
||||
`const a = 1;
|
||||
const c = 3;`,
|
||||
|
||||
"/bar.ts":
|
||||
`const b = 2;
|
||||
function add1(x: number, y: number): number;
|
||||
function add1(x: string, y: string): string;
|
||||
function add1(x: any, y: any) {
|
||||
return x + y;
|
||||
}
|
||||
function foo() { }
|
||||
function add2(x: number, y: number): number;
|
||||
function add2(x: string, y: string): string;
|
||||
function add2(x: any, y: any) {
|
||||
return x + y;
|
||||
}
|
||||
`,
|
||||
},
|
||||
interactiveRefactorArguments: { targetFile: "/bar.ts" }
|
||||
});
|
||||
24
tests/cases/fourslash/moveToFile_expandSelectionRange14.ts
Normal file
24
tests/cases/fourslash/moveToFile_expandSelectionRange14.ts
Normal file
@@ -0,0 +1,24 @@
|
||||
/// <reference path='fourslash.ts' />
|
||||
|
||||
//@Filename: /bar.ts
|
||||
////
|
||||
|
||||
// @Filename: /a.ts
|
||||
////export [|default class {
|
||||
//// run()|] {}
|
||||
////}
|
||||
|
||||
verify.moveToFile({
|
||||
newFileContents: {
|
||||
"/a.ts":
|
||||
``,
|
||||
|
||||
"/bar.ts":
|
||||
`
|
||||
export default class {
|
||||
run() { }
|
||||
}
|
||||
`,
|
||||
},
|
||||
interactiveRefactorArguments: { targetFile: "/bar.ts" }
|
||||
});
|
||||
20
tests/cases/fourslash/moveToFile_expandSelectionRange15.ts
Normal file
20
tests/cases/fourslash/moveToFile_expandSelectionRange15.ts
Normal file
@@ -0,0 +1,20 @@
|
||||
/// <reference path='fourslash.ts' />
|
||||
|
||||
//@Filename: /bar.ts
|
||||
////const a = 1;
|
||||
|
||||
// @Filename: /a.ts
|
||||
////let [|message: string, count: number = 10, functional|]: boolean = true;
|
||||
|
||||
verify.moveToFile({
|
||||
newFileContents: {
|
||||
"/a.ts":
|
||||
``,
|
||||
|
||||
"/bar.ts":
|
||||
`const a = 1;
|
||||
let message: string, count: number = 10, functional: boolean = true;
|
||||
`,
|
||||
},
|
||||
interactiveRefactorArguments: { targetFile: "/bar.ts" }
|
||||
});
|
||||
28
tests/cases/fourslash/moveToFile_expandSelectionRange2.ts
Normal file
28
tests/cases/fourslash/moveToFile_expandSelectionRange2.ts
Normal file
@@ -0,0 +1,28 @@
|
||||
/// <reference path='fourslash.ts' />
|
||||
|
||||
//@Filename: /bar.ts
|
||||
////import { b } from './other';
|
||||
////const t = b;
|
||||
|
||||
// @Filename: /a.ts
|
||||
////co[|nst a = 1;
|
||||
////cons|]t b = 1;
|
||||
////function foo() { }
|
||||
|
||||
// @Filename: /other.ts
|
||||
////export const b = 2;
|
||||
|
||||
verify.moveToFile({
|
||||
newFileContents: {
|
||||
"/a.ts":
|
||||
`function foo() { }`,
|
||||
|
||||
"/bar.ts":
|
||||
`import { b } from './other';
|
||||
const t = b;
|
||||
const a = 1;
|
||||
const b = 1;
|
||||
`,
|
||||
},
|
||||
interactiveRefactorArguments: { targetFile: "/bar.ts" }
|
||||
});
|
||||
28
tests/cases/fourslash/moveToFile_expandSelectionRange3.ts
Normal file
28
tests/cases/fourslash/moveToFile_expandSelectionRange3.ts
Normal file
@@ -0,0 +1,28 @@
|
||||
/// <reference path='fourslash.ts' />
|
||||
|
||||
//@Filename: /bar.ts
|
||||
////import { b } from './other';
|
||||
////const t = b;
|
||||
|
||||
// @Filename: /a.ts
|
||||
////[|const a = 1;
|
||||
////const b = 1;|]
|
||||
////function foo() { }
|
||||
|
||||
// @Filename: /other.ts
|
||||
////export const b = 2;
|
||||
|
||||
verify.moveToFile({
|
||||
newFileContents: {
|
||||
"/a.ts":
|
||||
`function foo() { }`,
|
||||
|
||||
"/bar.ts":
|
||||
`import { b } from './other';
|
||||
const t = b;
|
||||
const a = 1;
|
||||
const b = 1;
|
||||
`,
|
||||
},
|
||||
interactiveRefactorArguments: { targetFile: "/bar.ts" }
|
||||
});
|
||||
38
tests/cases/fourslash/moveToFile_expandSelectionRange4.ts
Normal file
38
tests/cases/fourslash/moveToFile_expandSelectionRange4.ts
Normal file
@@ -0,0 +1,38 @@
|
||||
/// <reference path='fourslash.ts' />
|
||||
|
||||
//@Filename: /bar.ts
|
||||
////import { b } from './other';
|
||||
////const t = b;
|
||||
|
||||
// @Filename: /a.ts
|
||||
//// interface T {
|
||||
//// a: number
|
||||
//// }
|
||||
//// const x: T={
|
||||
//// a: 1
|
||||
//// };
|
||||
//// [|const b = x|].a;
|
||||
|
||||
// @Filename: /other.ts
|
||||
////export const b = 2;
|
||||
|
||||
verify.moveToFile({
|
||||
newFileContents: {
|
||||
"/a.ts":
|
||||
`interface T {
|
||||
a: number
|
||||
}
|
||||
export const x: T={
|
||||
a: 1
|
||||
};
|
||||
`,
|
||||
|
||||
"/bar.ts":
|
||||
`import { x } from "./a";
|
||||
import { b } from './other';
|
||||
const t = b;
|
||||
const b = x.a;
|
||||
`,
|
||||
},
|
||||
interactiveRefactorArguments: { targetFile: "/bar.ts" }
|
||||
});
|
||||
25
tests/cases/fourslash/moveToFile_expandSelectionRange5.ts
Normal file
25
tests/cases/fourslash/moveToFile_expandSelectionRange5.ts
Normal file
@@ -0,0 +1,25 @@
|
||||
/// <reference path='fourslash.ts' />
|
||||
|
||||
//@Filename: /bar.ts
|
||||
////import { b } from './other';
|
||||
////const t = b;
|
||||
|
||||
// @Filename: /a.ts
|
||||
////fu[|nction f|]oo() { }
|
||||
|
||||
// @Filename: /other.ts
|
||||
////export const b = 2;
|
||||
|
||||
verify.moveToFile({
|
||||
newFileContents: {
|
||||
"/a.ts":
|
||||
``,
|
||||
|
||||
"/bar.ts":
|
||||
`import { b } from './other';
|
||||
const t = b;
|
||||
function foo() { }
|
||||
`,
|
||||
},
|
||||
interactiveRefactorArguments: { targetFile: "/bar.ts" }
|
||||
});
|
||||
26
tests/cases/fourslash/moveToFile_expandSelectionRange6.ts
Normal file
26
tests/cases/fourslash/moveToFile_expandSelectionRange6.ts
Normal file
@@ -0,0 +1,26 @@
|
||||
/// <reference path='fourslash.ts' />
|
||||
|
||||
//@Filename: /bar.ts
|
||||
////
|
||||
|
||||
// @Filename: /a.ts
|
||||
////[|function|] f() {
|
||||
////function inner() {}
|
||||
////}
|
||||
////const a = 1;
|
||||
|
||||
|
||||
verify.moveToFile({
|
||||
newFileContents: {
|
||||
"/a.ts":
|
||||
`const a = 1;`,
|
||||
|
||||
"/bar.ts":
|
||||
`
|
||||
function f() {
|
||||
function inner() { }
|
||||
}
|
||||
`,
|
||||
},
|
||||
interactiveRefactorArguments: { targetFile: "/bar.ts" }
|
||||
});
|
||||
24
tests/cases/fourslash/moveToFile_expandSelectionRange7.ts
Normal file
24
tests/cases/fourslash/moveToFile_expandSelectionRange7.ts
Normal file
@@ -0,0 +1,24 @@
|
||||
/// <reference path='fourslash.ts' />
|
||||
|
||||
//@Filename: /bar.ts
|
||||
////
|
||||
|
||||
// @Filename: /a.ts
|
||||
//// fun[|ction f() {
|
||||
//// cons|]t a = 1;
|
||||
//// }
|
||||
|
||||
verify.moveToFile({
|
||||
newFileContents: {
|
||||
"/a.ts":
|
||||
``,
|
||||
|
||||
"/bar.ts":
|
||||
`
|
||||
function f() {
|
||||
const a = 1;
|
||||
}
|
||||
`,
|
||||
},
|
||||
interactiveRefactorArguments: { targetFile: "/bar.ts" }
|
||||
});
|
||||
26
tests/cases/fourslash/moveToFile_expandSelectionRange8.ts
Normal file
26
tests/cases/fourslash/moveToFile_expandSelectionRange8.ts
Normal file
@@ -0,0 +1,26 @@
|
||||
/// <reference path='fourslash.ts' />
|
||||
|
||||
//@Filename: /bar.ts
|
||||
////import { b } from './other';
|
||||
////const t = b;
|
||||
|
||||
// @Filename: /a.ts
|
||||
////[|const a = 1;
|
||||
//// |]const b = 2;
|
||||
|
||||
// @Filename: /other.ts
|
||||
////export const b = 2;
|
||||
|
||||
verify.moveToFile({
|
||||
newFileContents: {
|
||||
"/a.ts":
|
||||
` const b = 2;`,
|
||||
|
||||
"/bar.ts":
|
||||
`import { b } from './other';
|
||||
const t = b;
|
||||
const a = 1;
|
||||
`,
|
||||
},
|
||||
interactiveRefactorArguments: { targetFile: "/bar.ts" }
|
||||
});
|
||||
27
tests/cases/fourslash/moveToFile_expandSelectionRange9.ts
Normal file
27
tests/cases/fourslash/moveToFile_expandSelectionRange9.ts
Normal file
@@ -0,0 +1,27 @@
|
||||
/// <reference path='fourslash.ts' />
|
||||
|
||||
//@Filename: /bar.ts
|
||||
////import { b } from './other';
|
||||
////const t = b;
|
||||
|
||||
// @Filename: /a.ts
|
||||
////const a = 1;[|
|
||||
////const c = 2;|]
|
||||
|
||||
// @Filename: /other.ts
|
||||
////export const b = 2;
|
||||
|
||||
verify.moveToFile({
|
||||
newFileContents: {
|
||||
"/a.ts":
|
||||
`const a = 1;
|
||||
`,
|
||||
|
||||
"/bar.ts":
|
||||
`import { b } from './other';
|
||||
const t = b;
|
||||
const c = 2;
|
||||
`,
|
||||
},
|
||||
interactiveRefactorArguments: { targetFile: "/bar.ts" }
|
||||
});
|
||||
@@ -5,4 +5,15 @@
|
||||
//// [|"use strict";|]
|
||||
////}
|
||||
|
||||
verify.noMoveToNewFile();
|
||||
verify.moveToNewFile({
|
||||
newFileContents: {
|
||||
"/a.ts":
|
||||
``,
|
||||
|
||||
"/foo.ts":
|
||||
`function foo() {
|
||||
"use strict";
|
||||
}
|
||||
`,
|
||||
},
|
||||
});
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
/// <reference path='fourslash.ts' />
|
||||
|
||||
// @Filename: /a.ts
|
||||
////[|const x = 0;
|
||||
////const|] y = 0;
|
||||
////function f() {
|
||||
//// [|function inner() {}|]
|
||||
////}
|
||||
|
||||
verify.noMoveToNewFile();
|
||||
@@ -1,19 +0,0 @@
|
||||
/// <reference path='fourslash.ts' />
|
||||
|
||||
// @Filename: /a.ts
|
||||
////[|const x = 0;
|
||||
////
|
||||
/////** Comm|]ent */
|
||||
////const y = 0;
|
||||
|
||||
verify.moveToNewFile({
|
||||
newFileContents: {
|
||||
"/a.ts":
|
||||
`/** Comment */
|
||||
const y = 0;`,
|
||||
|
||||
"/x.ts":
|
||||
`const x = 0;
|
||||
`,
|
||||
},
|
||||
});
|
||||
Reference in New Issue
Block a user