diff --git a/.vscode/launch.json b/.vscode/launch.json index e05a550..e8bacfb 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -50,7 +50,7 @@ "env": { "EXT_DEBUG": "true", "LOCAL_TEST": "true", - "COVERAGE": "true", + "COVERAGE": "", "CHAI_JEST_SNAPSHOT_UPDATE_ALL": "" }, "stopOnEntry": false, @@ -74,7 +74,7 @@ "env": { "EXT_DEBUG": "true", "LOCAL_TEST": "true", - "COVERAGE": "true", + "COVERAGE": "", "CHAI_JEST_SNAPSHOT_UPDATE_ALL": "" }, "stopOnEntry": false, diff --git a/src/utilities/utility-functions.ts b/src/utilities/utility-functions.ts index 5e7fb5a..4116aca 100644 --- a/src/utilities/utility-functions.ts +++ b/src/utilities/utility-functions.ts @@ -320,7 +320,7 @@ export function getRelativeLibraryName(library: string, actualFilePath: string, return toPosix(relativePath); } -const REGEX_IGNORED_LINE = /^\s*(?:\/\/|\/\*\*|\*\/|\*|(['"])use strict\1)/; +const REGEX_IGNORED_LINE = /^\s*(?:\/\/|\/\*|\*\/|\*|#!|(['"])use strict\1)/; /** * Calculate the position, where a new import should be inserted. diff --git a/test/etc/workspace_1/imports/import-appender-file.ts b/test/etc/workspace_1/imports/import-appender-file.ts new file mode 100644 index 0000000..e69de29 diff --git a/test/tests/imports/__snapshots__/import-appender.test.ts.snap b/test/tests/imports/__snapshots__/import-appender.test.ts.snap new file mode 100644 index 0000000..dec87b6 --- /dev/null +++ b/test/tests/imports/__snapshots__/import-appender.test.ts.snap @@ -0,0 +1,50 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`ImportAppender import-appender-file.ts should add a double normal named import 1`] = ` +"import { MyClass, MyClass2 } from '../lib'; +" +`; + +exports[`ImportAppender import-appender-file.ts should add a normal default import 1`] = ` +"import defaultDec from '../lib'; +" +`; + +exports[`ImportAppender import-appender-file.ts should add a normal named import 1`] = ` +"import { MyClass } from '../lib'; +" +`; + +exports[`ImportAppender import-appender-file.ts should add an import below a block comment 1`] = ` +"/* + * copy right by me! + */ +import { MyClass } from '../lib'; +" +`; + +exports[`ImportAppender import-appender-file.ts should add an import below a comment 1`] = ` +"// my fancy comment +import { MyClass } from '../lib'; +" +`; + +exports[`ImportAppender import-appender-file.ts should add an import below a jsdoc comment 1`] = ` +"/** + * js documentation! + */ +import { MyClass } from '../lib'; +" +`; + +exports[`ImportAppender import-appender-file.ts should add an import below a shebang 1`] = ` +"#! /usr/bin/env node +import { MyClass } from '../lib'; +" +`; + +exports[`ImportAppender import-appender-file.ts should add an import below a use strict 1`] = ` +"\\"use strict\\" +import { MyClass } from '../lib'; +" +`; diff --git a/test/tests/imports/import-appender.test.ts b/test/tests/imports/import-appender.test.ts index e69de29..42e12b0 100644 --- a/test/tests/imports/import-appender.test.ts +++ b/test/tests/imports/import-appender.test.ts @@ -0,0 +1,141 @@ +import { join } from 'path'; +import { ClassDeclaration, DeclarationInfo, DefaultDeclaration, File } from 'typescript-parser'; +import { Position, Range, TextDocument, Uri, window, workspace } from 'vscode'; + +import { ImportAppender } from '../../../src/imports'; +import ioc from '../../../src/ioc'; +import iocSymbols from '../../../src/ioc-symbols'; +import { expect } from '../setup'; + +describe('ImportAppender', () => { + + describe('import-appender-file.ts', () => { + + const rootPath = workspace.workspaceFolders![0].uri.fsPath; + const file = Uri.file(join(rootPath, 'imports', 'import-appender-file.ts')); + let document: TextDocument; + let extension: { addImportToDocument(declaration: DeclarationInfo): Promise }; + + before(async () => { + document = await workspace.openTextDocument(file); + await window.showTextDocument(document); + + extension = new ImportAppender( + ioc.get(iocSymbols.extensionContext), + ioc.get(iocSymbols.logger), + ioc.get(iocSymbols.importManager), + ioc.get(iocSymbols.declarationManager), + ioc.get(iocSymbols.parser), + ) as any; + }); + + afterEach(async () => { + await window.activeTextEditor!.edit((builder) => { + builder.delete(new Range( + new Position(0, 0), + document.lineAt(document.lineCount - 1).rangeIncludingLineBreak.end, + )); + }); + }); + + it('should add a normal named import', async () => { + await extension.addImportToDocument({ + from: '/lib', + declaration: new ClassDeclaration('MyClass', true, 0, 0), + }); + expect(window.activeTextEditor!.document.getText()).to.matchSnapshot(); + }); + + it('should add a double normal named import', async () => { + await extension.addImportToDocument({ + from: '/lib', + declaration: new ClassDeclaration('MyClass', true, 0, 0), + }); + await extension.addImportToDocument({ + from: '/lib', + declaration: new ClassDeclaration('MyClass2', true, 0, 0), + }); + expect(window.activeTextEditor!.document.getText()).to.matchSnapshot(); + }); + + it('should add a normal default import', async () => { + await extension.addImportToDocument({ + from: '/lib', + declaration: new DefaultDeclaration('defaultDec', new File(file.fsPath, rootPath, 0, 0), 0, 0), + }); + expect(window.activeTextEditor!.document.getText()).to.matchSnapshot(); + }); + + it('should add an import below a comment', async () => { + await window.activeTextEditor!.edit((builder) => { + builder.insert( + new Position(0, 0), + `// my fancy comment\n`, + ); + }); + await extension.addImportToDocument({ + from: '/lib', + declaration: new ClassDeclaration('MyClass', true, 0, 0), + }); + expect(window.activeTextEditor!.document.getText()).to.matchSnapshot(); + }); + + it('should add an import below a block comment', async () => { + await window.activeTextEditor!.edit((builder) => { + builder.insert( + new Position(0, 0), + `/* \n * copy right by me!\n */\n`, + ); + }); + await extension.addImportToDocument({ + from: '/lib', + declaration: new ClassDeclaration('MyClass', true, 0, 0), + }); + expect(window.activeTextEditor!.document.getText()).to.matchSnapshot(); + }); + + it('should add an import below a jsdoc comment', async () => { + await window.activeTextEditor!.edit((builder) => { + builder.insert( + new Position(0, 0), + `/** \n * js documentation!\n */\n`, + ); + }); + await extension.addImportToDocument({ + from: '/lib', + declaration: new ClassDeclaration('MyClass', true, 0, 0), + }); + expect(window.activeTextEditor!.document.getText()).to.matchSnapshot(); + }); + + it('should add an import below a shebang', async () => { + await window.activeTextEditor!.edit((builder) => { + builder.insert( + new Position(0, 0), + `#! /usr/bin/env node\n`, + ); + }); + await extension.addImportToDocument({ + from: '/lib', + declaration: new ClassDeclaration('MyClass', true, 0, 0), + }); + expect(window.activeTextEditor!.document.getText()).to.matchSnapshot(); + }); + + it('should add an import below a use strict', async () => { + await window.activeTextEditor!.edit((builder) => { + builder.insert( + new Position(0, 0), + `"use strict"\n`, + ); + }); + await extension.addImportToDocument({ + from: '/lib', + declaration: new ClassDeclaration('MyClass', true, 0, 0), + }); + expect(window.activeTextEditor!.document.getText()).to.matchSnapshot(); + }); + + }); + +}); diff --git a/test/tests/utilities/__snapshots__/utility-functions.test.ts.snap b/test/tests/utilities/__snapshots__/utility-functions.test.ts.snap index addaef1..26a89b3 100644 --- a/test/tests/utilities/__snapshots__/utility-functions.test.ts.snap +++ b/test/tests/utilities/__snapshots__/utility-functions.test.ts.snap @@ -7,6 +7,13 @@ Object { } `; +exports[`utility functions getImportInsertPosition() should return correct position for js block comment open 1`] = ` +Object { + "character": 0, + "line": 1, +} +`; + exports[`utility functions getImportInsertPosition() should return correct position for jsdoc comment close 1`] = ` Object { "character": 0, @@ -28,6 +35,13 @@ Object { } `; +exports[`utility functions getImportInsertPosition() should return correct position for shebang (#!) 1`] = ` +Object { + "character": 0, + "line": 1, +} +`; + exports[`utility functions getImportInsertPosition() should return correct position for use strict 1`] = ` Object { "character": 0, diff --git a/test/tests/utilities/utility-functions.test.ts b/test/tests/utilities/utility-functions.test.ts index cb13ace..4341742 100644 --- a/test/tests/utilities/utility-functions.test.ts +++ b/test/tests/utilities/utility-functions.test.ts @@ -57,6 +57,13 @@ describe('utility functions', () => { expect(pos).to.matchSnapshot(); }); + it('should return correct position for js block comment open', () => { + const pos = getImportInsertPosition({ + document: new MockDocument('/* yay\n'), + } as any); + expect(pos).to.matchSnapshot(); + }); + it('should return correct position for jsdoc comment line', () => { const pos = getImportInsertPosition({ document: new MockDocument(' * jsdoc line\n'), @@ -71,6 +78,13 @@ describe('utility functions', () => { expect(pos).to.matchSnapshot(); }); + it('should return correct position for shebang (#!)', () => { + const pos = getImportInsertPosition({ + document: new MockDocument('#!\n'), + } as any); + expect(pos).to.matchSnapshot(); + }); + }); describe('importGroupSortForPrecedence', () => {