diff --git a/src/services/textChanges.ts b/src/services/textChanges.ts index 1fa19379afc4c..06db03c71b4cc 100644 --- a/src/services/textChanges.ts +++ b/src/services/textChanges.ts @@ -1275,7 +1275,15 @@ namespace changesToText { const targetSourceFile = c.kind === ChangeKind.ReplaceWithSingleNode ? getSourceFileOfNode(getOriginalNode(c.node)) ?? c.sourceFile : c.kind === ChangeKind.ReplaceWithMultipleNodes ? getSourceFileOfNode(getOriginalNode(c.nodes[0])) ?? c.sourceFile : c.sourceFile; - const newText = computeNewText(c, targetSourceFile, sourceFile, newLineCharacter, formatContext, validate); + let newText = computeNewText(c, targetSourceFile, sourceFile, newLineCharacter, formatContext, validate); + + // prevent appending an extra new line to declarations at end of a file + const spanTextEnd = span.start + newText.length; + const isEndOfFile = span.length !== 0 && (spanTextEnd - newLineCharacter.length) === targetSourceFile.text.length; + if (c.kind === ChangeKind.ReplaceWithMultipleNodes && isEndOfFile && endsWith(newText, newLineCharacter)) { + newText = newText.substring(0, newText.length - newLineCharacter.length); + } + // Filter out redundant changes. if (span.length === newText.length && stringContainsAt(targetSourceFile.text, newText, span.start)) { return undefined; diff --git a/tests/baselines/reference/organizeImports/TypeOnly.ts b/tests/baselines/reference/organizeImports/TypeOnly.ts index 96281b4ada53a..d98ebcb23af35 100644 --- a/tests/baselines/reference/organizeImports/TypeOnly.ts +++ b/tests/baselines/reference/organizeImports/TypeOnly.ts @@ -12,4 +12,4 @@ import type Y from "lib"; import type { A, B } from "lib"; import { X, Z } from "lib"; -export { A, B, X, Y, Z }; +export { A, B, X, Y, Z }; \ No newline at end of file diff --git a/tests/cases/fourslash/organizeImports12.ts b/tests/cases/fourslash/organizeImports12.ts index 04b0e0214eac7..5b1d978f898c7 100644 --- a/tests/cases/fourslash/organizeImports12.ts +++ b/tests/cases/fourslash/organizeImports12.ts @@ -9,5 +9,5 @@ verify.organizeImports( `declare export default class A {} declare export * from "foo"; -declare export { a, b }; -`); +declare export { a, b };` +); diff --git a/tests/cases/fourslash/organizeImports17.ts b/tests/cases/fourslash/organizeImports17.ts index a72a7a054e7a0..4b0e84e980d5a 100644 --- a/tests/cases/fourslash/organizeImports17.ts +++ b/tests/cases/fourslash/organizeImports17.ts @@ -5,8 +5,7 @@ verify.organizeImports( `import { case, Insensitively, sorted } from "aardvark"; -import { Both } from "module-specifiers-unsorted"; -`, +import { Both } from "module-specifiers-unsorted";`, ts.OrganizeImportsMode.SortAndCombine, { organizeImportsIgnoreCase: "auto", diff --git a/tests/cases/fourslash/organizeImports18.ts b/tests/cases/fourslash/organizeImports18.ts index 12ee4ef6cac9f..acbad3a166458 100644 --- a/tests/cases/fourslash/organizeImports18.ts +++ b/tests/cases/fourslash/organizeImports18.ts @@ -29,5 +29,5 @@ export { C } from "./C"; export { bFuncA } from "./A"; export { bFuncB } from "./B"; -export { bFuncC } from "./C"; -`); +export { bFuncC } from "./C";` +); diff --git a/tests/cases/fourslash/organizeImports19.ts b/tests/cases/fourslash/organizeImports19.ts index c7d00c70059d8..9908e31021d45 100644 --- a/tests/cases/fourslash/organizeImports19.ts +++ b/tests/cases/fourslash/organizeImports19.ts @@ -17,5 +17,5 @@ const b = 1; export { b }; const c = 1; -export { c }; -`); +export { c };` +); diff --git a/tests/cases/fourslash/organizeImports24.ts b/tests/cases/fourslash/organizeImports24.ts new file mode 100644 index 0000000000000..de5f8e4329dbd --- /dev/null +++ b/tests/cases/fourslash/organizeImports24.ts @@ -0,0 +1,9 @@ +/// + +//// export * from './file2.js'; +//// export * from './file1.js'; + +verify.organizeImports( +`export * from './file1.js'; +export * from './file2.js';` +); diff --git a/tests/cases/fourslash/organizeImports25.ts b/tests/cases/fourslash/organizeImports25.ts new file mode 100644 index 0000000000000..91a9c393b8022 --- /dev/null +++ b/tests/cases/fourslash/organizeImports25.ts @@ -0,0 +1,15 @@ +/// + +//// export * from './file4.js'; +//// export * from './file3.js'; +//// +//// export * from './file2.js'; +//// export * from './file1.js'; + +verify.organizeImports( +`export * from './file3.js'; +export * from './file4.js'; + +export * from './file1.js'; +export * from './file2.js';` +); diff --git a/tests/cases/fourslash/organizeImports26.ts b/tests/cases/fourslash/organizeImports26.ts new file mode 100644 index 0000000000000..912180ebe1a3b --- /dev/null +++ b/tests/cases/fourslash/organizeImports26.ts @@ -0,0 +1,11 @@ +/// + +//// export * from './file1.js'; +//// export * from './file2.js'; +//// + +verify.organizeImports( +`export * from './file1.js'; +export * from './file2.js'; +` +); diff --git a/tests/cases/fourslash/organizeImportsType2.ts b/tests/cases/fourslash/organizeImportsType2.ts index 57b2b4db26950..24b0a099e8e45 100644 --- a/tests/cases/fourslash/organizeImportsType2.ts +++ b/tests/cases/fourslash/organizeImportsType2.ts @@ -15,16 +15,14 @@ verify.organizeImports( `type A = string; type B = string; const C = "hello"; -export { A, C, type B }; -` +export { A, C, type B };` ); verify.organizeImports( `type A = string; type B = string; const C = "hello"; -export { A, type B, C }; -`, +export { A, type B, C };`, undefined, { organizeImportsTypeOrder : "inline" } ); @@ -33,8 +31,7 @@ verify.organizeImports( `type A = string; type B = string; const C = "hello"; -export { type B, A, C }; -`, +export { type B, A, C };`, undefined, { organizeImportsTypeOrder : "first" } ); @@ -43,8 +40,7 @@ verify.organizeImports( `type A = string; type B = string; const C = "hello"; -export { A, C, type B }; -`, +export { A, C, type B };`, undefined, { organizeImportsTypeOrder : "last" } ); \ No newline at end of file