From 8a522add3788c0ea5d2947b241ccb99a4f5e2528 Mon Sep 17 00:00:00 2001 From: "greenkeeper[bot]" Date: Tue, 26 Sep 2017 08:23:40 +0000 Subject: [PATCH 1/6] chore(package): update sinon to version 4.0.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index f9dcc35..fe7702c 100644 --- a/package.json +++ b/package.json @@ -101,7 +101,7 @@ "mocha-testdata": "^1.2.0", "semantic-release": "^8.0.0", "semantic-release-visualstudio-marketplace-version": "^1.0.0", - "sinon": "^3.2.1", + "sinon": "^4.0.0", "sinon-chai": "^2.13.0", "tslint": "^5.7.0", "tslint-config-airbnb": "^5.3.0-beta", From 657726de909e6942a8f1c589a1f89d124e979b11 Mon Sep 17 00:00:00 2001 From: "greenkeeper[bot]" Date: Tue, 26 Sep 2017 08:43:15 +0000 Subject: [PATCH 2/6] chore(package): update lockfile https://npm.im/greenkeeper-lockfile --- yarn.lock | 123 +++++------------------------------------------------- 1 file changed, 10 insertions(+), 113 deletions(-) diff --git a/yarn.lock b/yarn.lock index c4836e3..7718b81 100644 --- a/yarn.lock +++ b/yarn.lock @@ -230,10 +230,6 @@ async@^2.0.1: dependencies: lodash "^4.14.0" -async@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/async/-/async-1.0.0.tgz#f8fc04ca3a13784ade9e1641af98578cfbd647a9" - asynckit@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" @@ -328,21 +324,6 @@ buffer-crc32@~0.2.3: version "0.2.13" resolved "https://registry.yarnpkg.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242" -build@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/build/-/build-0.1.4.tgz#707fe026ffceddcacbfdcdf356eafda64f151046" - dependencies: - cssmin "0.3.x" - jsmin "1.x" - jxLoader "*" - moo-server "*" - promised-io "*" - timespan "2.x" - uglify-js "1.x" - walker "1.x" - winston "*" - wrench "1.3.x" - builtin-modules@^1.0.0: version "1.1.1" resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-1.1.1.tgz#270f076c5a72c02f5b65a47df94c5fe3a278892f" @@ -476,10 +457,6 @@ color-name@^1.1.1: version "1.1.3" resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" -colors@1.0.x: - version "1.0.3" - resolved "https://registry.yarnpkg.com/colors/-/colors-1.0.3.tgz#0433f44d809680fdeb60ed260f1b0c262e82a40b" - colors@^1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/colors/-/colors-1.1.2.tgz#168a4701756b6a7f51a12ce0c97bfa28c084ed63" @@ -642,20 +619,12 @@ crypto-random-string@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/crypto-random-string/-/crypto-random-string-1.0.0.tgz#a230f64f568310e1498009940790ec99545bca7e" -cssmin@0.3.x: - version "0.3.2" - resolved "https://registry.yarnpkg.com/cssmin/-/cssmin-0.3.2.tgz#ddce4c547b510ae0d594a8f1fbf8aaf8e2c5c00d" - currently-unhandled@^0.4.1: version "0.4.1" resolved "https://registry.yarnpkg.com/currently-unhandled/-/currently-unhandled-0.4.1.tgz#988df33feab191ef799a61369dd76c17adf957ea" dependencies: array-find-index "^1.0.1" -cycle@1.0.x: - version "1.0.3" - resolved "https://registry.yarnpkg.com/cycle/-/cycle-1.0.3.tgz#21e80b2be8580f98b468f379430662b046c34ad2" - dargs@^4.0.1: version "4.1.0" resolved "https://registry.yarnpkg.com/dargs/-/dargs-4.1.0.tgz#03a9dbb4b5c2f139bf14ae53f0b8a2a6a86f4e17" @@ -879,10 +848,6 @@ extsprintf@1.3.0, extsprintf@^1.2.0: version "1.3.0" resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05" -eyes@0.1.x: - version "0.1.8" - resolved "https://registry.yarnpkg.com/eyes/-/eyes-0.1.8.tgz#62cf120234c683785d902348a800ef3e0cc20bc0" - fancy-log@^1.1.0: version "1.3.0" resolved "https://registry.yarnpkg.com/fancy-log/-/fancy-log-1.3.0.tgz#45be17d02bb9917d60ccffd4995c999e6c8c9948" @@ -1654,7 +1619,7 @@ isobject@^2.0.0: dependencies: isarray "1.0.0" -isstream@0.1.x, isstream@~0.1.2: +isstream@~0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" @@ -1662,10 +1627,6 @@ js-tokens@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b" -js-yaml@0.3.x: - version "0.3.7" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-0.3.7.tgz#d739d8ee86461e54b354d6a7d7d1f2ad9a167f62" - js-yaml@3.6.1: version "3.6.1" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.6.1.tgz#6e5fe67d8b205ce4d22fad05b7781e8dadcc4b30" @@ -1677,10 +1638,6 @@ jsbn@~0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" -jsmin@1.x: - version "1.0.1" - resolved "https://registry.yarnpkg.com/jsmin/-/jsmin-1.0.1.tgz#e7bd0dcd6496c3bf4863235bf461a3d98aa3b98c" - json-schema@0.2.3: version "0.2.3" resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13" @@ -1724,15 +1681,6 @@ just-extend@^1.1.22: version "1.1.22" resolved "https://registry.yarnpkg.com/just-extend/-/just-extend-1.1.22.tgz#3330af756cab6a542700c64b2e4e4aa062d52fff" -jxLoader@*: - version "0.1.1" - resolved "https://registry.yarnpkg.com/jxLoader/-/jxLoader-0.1.1.tgz#0134ea5144e533b594fc1ff25ff194e235c53ecd" - dependencies: - js-yaml "0.3.x" - moo-server "1.3.x" - promised-io "*" - walker "1.x" - kind-of@^3.0.2: version "3.2.2" resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" @@ -1978,12 +1926,6 @@ make-dir@^1.0.0: dependencies: pify "^2.3.0" -makeerror@1.0.x: - version "1.0.11" - resolved "https://registry.yarnpkg.com/makeerror/-/makeerror-1.0.11.tgz#e01a5c9109f2af79660e4e8b9587790184f5a96c" - dependencies: - tmpl "1.0.x" - map-obj@^1.0.0, map-obj@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-1.0.1.tgz#d933ceb9205d82bdcf4886f6742bdc2b4dea146d" @@ -2090,10 +2032,6 @@ modify-values@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/modify-values/-/modify-values-1.0.0.tgz#e2b6cdeb9ce19f99317a53722f3dbf5df5eaaab2" -moo-server@*, moo-server@1.3.x: - version "1.3.0" - resolved "https://registry.yarnpkg.com/moo-server/-/moo-server-1.3.0.tgz#5dc79569565a10d6efed5439491e69d2392e58f1" - ms@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" @@ -2125,14 +2063,15 @@ netrc@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/netrc/-/netrc-0.1.4.tgz#6be94fcaca8d77ade0a9670dc460914c94472444" -nise@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/nise/-/nise-1.0.1.tgz#0da92b10a854e97c0f496f6c2845a301280b3eef" +nise@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/nise/-/nise-1.1.0.tgz#37e41b9bf0041ccb83d1bf03e79440bbc0db10ad" dependencies: formatio "^1.2.0" just-extend "^1.1.22" lolex "^1.6.0" path-to-regexp "^1.7.0" + text-encoding "^0.6.4" node-uuid@~1.4.7: version "1.4.8" @@ -2427,10 +2366,6 @@ process-nextick-args@^1.0.6, process-nextick-args@~1.0.6: version "1.0.7" resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-1.0.7.tgz#150e20b756590ad3f91093f25a4f2ad8bff30ba3" -promised-io@*: - version "0.3.5" - resolved "https://registry.yarnpkg.com/promised-io/-/promised-io-0.3.5.tgz#4ad217bb3658bcaae9946b17a8668ecd851e1356" - proto-list@~1.2.1: version "1.2.4" resolved "https://registry.yarnpkg.com/proto-list/-/proto-list-1.2.4.tgz#212d5bfe1318306a420f6402b8e26ff39647a849" @@ -2798,17 +2733,16 @@ sinon-chai@^2.13.0: version "2.13.0" resolved "https://registry.yarnpkg.com/sinon-chai/-/sinon-chai-2.13.0.tgz#b9a42e801c20234bfc2f43b29e6f4f61b60990c4" -sinon@^3.2.1: - version "3.3.0" - resolved "https://registry.yarnpkg.com/sinon/-/sinon-3.3.0.tgz#9132111b4bbe13c749c2848210864250165069b1" +sinon@4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/sinon/-/sinon-4.0.0.tgz#a54a5f0237aa1dd2215e5e81c89b42b50c4fdb6b" dependencies: - build "^0.1.4" diff "^3.1.0" formatio "1.2.0" lodash.get "^4.4.2" lolex "^2.1.2" native-promise-only "^0.8.1" - nise "^1.0.1" + nise "^1.1.0" path-to-regexp "^1.7.0" samsam "^1.1.3" text-encoding "0.6.4" @@ -2898,10 +2832,6 @@ sshpk@^1.7.0: jsbn "~0.1.0" tweetnacl "~0.14.0" -stack-trace@0.0.x: - version "0.0.10" - resolved "https://registry.yarnpkg.com/stack-trace/-/stack-trace-0.0.10.tgz#547c70b347e8d32b4e108ea1a2a159e5fdde19c0" - stat-mode@^0.2.0: version "0.2.2" resolved "https://registry.yarnpkg.com/stat-mode/-/stat-mode-0.2.2.tgz#e6c80b623123d7d80cf132ce538f346289072502" @@ -3028,7 +2958,7 @@ term-size@^1.2.0: dependencies: execa "^0.7.0" -text-encoding@0.6.4: +text-encoding@0.6.4, text-encoding@^0.6.4: version "0.6.4" resolved "https://registry.yarnpkg.com/text-encoding/-/text-encoding-0.6.4.tgz#e399a982257a276dae428bb92845cb71bdc26d19" @@ -3069,14 +2999,6 @@ timed-out@^4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/timed-out/-/timed-out-4.0.1.tgz#f32eacac5a175bea25d7fab565ab3ed8741ef56f" -timespan@2.x: - version "2.3.0" - resolved "https://registry.yarnpkg.com/timespan/-/timespan-2.3.0.tgz#4902ce040bd13d845c8f59b27e9d59bad6f39929" - -tmpl@1.0.x: - version "1.0.4" - resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.4.tgz#23640dd7b42d00433911140820e5cf440e521dd1" - to-absolute-glob@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/to-absolute-glob/-/to-absolute-glob-0.1.1.tgz#1cdfa472a9ef50c239ee66999b662ca0eb39937f" @@ -3222,10 +3144,6 @@ typescript@2.4.2, typescript@~2.4.2: version "2.4.2" resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.4.2.tgz#f8395f85d459276067c988aa41837a8f82870844" -uglify-js@1.x: - version "1.3.5" - resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-1.3.5.tgz#4b5bfff9186effbaa888e4c9e94bd9fc4c94929d" - uglify-js@^2.6: version "2.8.29" resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-2.8.29.tgz#29c5733148057bb4e1f75df35b7a9cb72e6a59dd" @@ -3412,12 +3330,6 @@ walk@^2.3.9: dependencies: foreachasync "^3.0.0" -walker@1.x: - version "1.0.7" - resolved "https://registry.yarnpkg.com/walker/-/walker-1.0.7.tgz#2f7f9b8fd10d677262b18a884e28d19618e028fb" - dependencies: - makeerror "1.0.x" - which@^1.2.9: version "1.3.0" resolved "https://registry.yarnpkg.com/which/-/which-1.3.0.tgz#ff04bdfc010ee547d780bec38e1ac1c2777d253a" @@ -3440,17 +3352,6 @@ window-size@0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/window-size/-/window-size-0.1.0.tgz#5438cd2ea93b202efa3a19fe8887aee7c94f9c9d" -winston@*: - version "2.3.1" - resolved "https://registry.yarnpkg.com/winston/-/winston-2.3.1.tgz#0b48420d978c01804cf0230b648861598225a119" - dependencies: - async "~1.0.0" - colors "1.0.x" - cycle "1.0.x" - eyes "0.1.x" - isstream "0.1.x" - stack-trace "0.0.x" - wordwrap@0.0.2: version "0.0.2" resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.2.tgz#b79669bb42ecb409f83d583cad52ca17eaa1643f" @@ -3463,10 +3364,6 @@ wrappy@1: version "1.0.2" resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" -wrench@1.3.x: - version "1.3.9" - resolved "https://registry.yarnpkg.com/wrench/-/wrench-1.3.9.tgz#6f13ec35145317eb292ca5f6531391b244111411" - write-file-atomic@^2.0.0: version "2.3.0" resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-2.3.0.tgz#1ff61575c2e2a4e8e510d6fa4e243cce183999ab" From 14d1af3e4cda571cc010af5618dbbbbcd56e4ccd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20B=C3=BChler?= Date: Wed, 4 Oct 2017 17:35:08 +0200 Subject: [PATCH 3/6] feat(parser): Upgrade typescript parser and update default import generation (#313) Closes #227. Closes #305. Does update the typescript parser and adjusts to the breaking changes of the parser. --- package.json | 16 +- src/common/helpers/DeclarationIndexHelpers.ts | 25 +- src/extension/extension.ts | 24 +- src/extension/managers/ImportManager.ts | 97 +++---- .../ImportsStructureTreeItem.ts | 27 +- src/extension/proxy-objects/ImportProxy.ts | 90 ------- .../DocumentSymbolStructureExtension.test.ts | 32 +-- test/extension/managers/ImportManager.test.ts | 34 ++- .../proxy-objects/ImportProxy.test.ts | 247 ------------------ tslint.json | 9 +- yarn.lock | 236 +++++++++-------- 11 files changed, 245 insertions(+), 592 deletions(-) delete mode 100644 src/extension/proxy-objects/ImportProxy.ts delete mode 100644 test/extension/proxy-objects/ImportProxy.test.ts diff --git a/package.json b/package.json index fe7702c..3ba1d96 100644 --- a/package.json +++ b/package.json @@ -91,21 +91,21 @@ "devDependencies": { "@types/chai": "^4.0.4", "@types/mocha": "^2.2.43", - "@types/node": "^8.0.28", + "@types/node": "^8.0.31", "@types/reflect-metadata": "0.0.5", - "@types/sinon": "^2.3.4", + "@types/sinon": "^2.3.5", "@types/sinon-chai": "^2.7.29", "chai": "^4.1.2", "del-cli": "^1.1.0", "filewalker": "^0.1.3", "mocha-testdata": "^1.2.0", - "semantic-release": "^8.0.0", + "semantic-release": "^8.0.3", "semantic-release-visualstudio-marketplace-version": "^1.0.0", "sinon": "^4.0.0", - "sinon-chai": "^2.13.0", + "sinon-chai": "^2.14.0", "tslint": "^5.7.0", - "tslint-config-airbnb": "^5.3.0-beta", - "tsutils": "^2.8.2", + "tslint-config-airbnb": "^5.3.0", + "tsutils": "^2.11.1", "vscode": "^1.1.5" }, "dependencies": { @@ -113,8 +113,8 @@ "inversify-inject-decorators": "^3.0.1", "reflect-metadata": "^0.1.10", "tslib": "^1.7.1", - "typescript": "~2.4.2", - "typescript-parser": "^1.3.3" + "typescript": "~2.5.3", + "typescript-parser": "^2.0.0" }, "activationEvents": [ "onLanguage:typescript", diff --git a/src/common/helpers/DeclarationIndexHelpers.ts b/src/common/helpers/DeclarationIndexHelpers.ts index 09dc42c..f131565 100644 --- a/src/common/helpers/DeclarationIndexHelpers.ts +++ b/src/common/helpers/DeclarationIndexHelpers.ts @@ -1,18 +1,10 @@ import { join, normalize, parse, relative } from 'path'; -import { - DeclarationInfo, - DefaultDeclaration, - DefaultImport, - ExternalModuleImport, - Import, - NamedImport, - NamespaceImport, -} from 'typescript-parser'; +import { DeclarationInfo, ExternalModuleImport, Import, NamedImport, NamespaceImport } from 'typescript-parser'; /** * Calculates a list of declarationInfos filtered by the already imported ones in the given document. * The result is a list of declarations that are not already imported by the document. - * + * * @export * @param {ResolveIndex} resolveIndex * @param {string} documentPath @@ -35,11 +27,14 @@ export function getDeclarationsFilteredByImports( declarations = declarations .filter(o => o.from !== importedLib || !(tsImport as NamedImport).specifiers .some(s => s.specifier === o.declaration.name)); + // if (tsImport.defaultAlias) { + // else if (tsImport instanceof DefaultImport) { + // declarations = declarations + // .filter(o => (!(o.declaration instanceof DefaultDeclaration) || importedLib !== o.from)); + // } + // } } else if (tsImport instanceof NamespaceImport || tsImport instanceof ExternalModuleImport) { declarations = declarations.filter(o => o.from !== tsImport.libraryName); - } else if (tsImport instanceof DefaultImport) { - declarations = declarations - .filter(o => (!(o.declaration instanceof DefaultDeclaration) || importedLib !== o.from)); } } @@ -51,7 +46,7 @@ export function getDeclarationsFilteredByImports( * If the library is a node module or a typings module, the name * is returned. If the "lib" is in the local workspace, then the * absolut path from the workspace root is returned. - * + * * @param {string} library Name of the library * @param {string} actualFilePath Filepath of the actually open file * @param {string} [rootPath] Root path of the workspace @@ -72,7 +67,7 @@ export function getAbsolutLibraryName(library: string, actualFilePath: string, r * If the library is a node module or a typings module, the name * is returned. If the "lib" is in the local workspace, then the * relative path from the actual file is returned. - * + * * @param {string} library Name of the library * @param {string} actualFilePath Filepath of the actually open file * @param {string} [rootPath] Root path of the workspace diff --git a/src/extension/extension.ts b/src/extension/extension.ts index 7c8b365..84aac90 100644 --- a/src/extension/extension.ts +++ b/src/extension/extension.ts @@ -1,12 +1,11 @@ import 'reflect-metadata'; -import { DefaultImport, GENERATORS, NamedImport, SymbolSpecifier, TypescriptCodeGenerator } from 'typescript-parser'; +import { GENERATORS, TypescriptCodeGenerator } from 'typescript-parser'; import { Disposable, ExtensionContext } from 'vscode'; import { KeywordImportGroup, RegexImportGroup, RemainImportGroup } from './import-grouping'; import { Container } from './IoC'; import { iocSymbols } from './IoCSymbols'; -import { ImportProxy } from './proxy-objects/ImportProxy'; import { TypeScriptHero } from './TypeScriptHero'; let extension: Disposable; @@ -25,28 +24,11 @@ function extendGenerator(generator: TypescriptCodeGenerator): void { GENERATORS[KeywordImportGroup.name] = simpleGenerator; GENERATORS[RegexImportGroup.name] = simpleGenerator; GENERATORS[RemainImportGroup.name] = simpleGenerator; - GENERATORS[ImportProxy.name] = (proxy: ImportProxy) => { - if (proxy.specifiers.length <= 0 && (proxy.defaultAlias || proxy.defaultPurposal)) { - return generator.generate( - new DefaultImport( - proxy.libraryName, (proxy.defaultAlias || proxy.defaultPurposal)!, proxy.start, proxy.end, - ), - ); - } - if (proxy.defaultAlias) { - proxy.specifiers.push(new SymbolSpecifier('default', proxy.defaultAlias)); - } - const named = new NamedImport( - proxy.libraryName, proxy.start, proxy.end, - ); - named.specifiers = proxy.specifiers; - return generator.generate(named); - }; } /** * Activates TypeScript Hero - * + * * @export * @param {ExtensionContext} context */ @@ -61,7 +43,7 @@ export async function activate(context: ExtensionContext): Promise { /** * Deactivates TypeScript Hero - * + * * @export */ export function deactivate(): void { diff --git a/src/extension/managers/ImportManager.ts b/src/extension/managers/ImportManager.ts index 8a20d55..38a44c2 100644 --- a/src/extension/managers/ImportManager.ts +++ b/src/extension/managers/ImportManager.ts @@ -2,7 +2,6 @@ import { DeclarationIndex, DeclarationInfo, DefaultDeclaration, - DefaultImport, ExternalModuleImport, File, Import, @@ -29,10 +28,21 @@ import { importRange } from '../helpers'; import { ImportGroup } from '../import-grouping'; import { Container } from '../IoC'; import { iocSymbols } from '../IoCSymbols'; -import { ImportProxy } from '../proxy-objects/ImportProxy'; import { importSort, specifierSort } from '../utilities/utilityFunctions'; import { ObjectManager } from './ObjectManager'; +function sameSpecifiers(specs1: SymbolSpecifier[], specs2: SymbolSpecifier[]): boolean { + for (const spec of specs1) { + const spec2 = specs2[specs1.indexOf(spec)]; + if (!spec2 || + spec.specifier !== spec2.specifier || + spec.alias !== spec2.alias) { + return false; + } + } + return true; +} + /** * Management class for the imports of a document. Can add and remove imports to the document * and commit the virtual document to the TextEditor. @@ -93,9 +103,6 @@ export class ImportManager implements ObjectManager { */ public static async create(document: TextDocument): Promise { const source = await ImportManager.parser.parseSource(document.getText()); - source.imports = source.imports.map( - o => o instanceof NamedImport || o instanceof DefaultImport ? new ImportProxy(o) : o, - ); return new ImportManager(document, source); } @@ -121,44 +128,39 @@ export class ImportManager implements ObjectManager { * @memberof ImportManager */ public addDeclarationImport(declarationInfo: DeclarationInfo): this { - // If there is something already imported, it must be a NamedImport or a DefaultImport - const alreadyImported: ImportProxy = this.imports.find( + // If there is something already imported, it must be a NamedImport + const alreadyImported: NamedImport = this.imports.find( o => declarationInfo.from === getAbsolutLibraryName( o.libraryName, this.document.fileName, ImportManager.rootPath, - ) && o instanceof ImportProxy, - ) as ImportProxy; + ) && o instanceof NamedImport, + ) as NamedImport; if (alreadyImported) { - // If we found an import for this declaration, it's either a default import or a named import + // If we found an import for this declaration, it's named import (with a possible default declaration) if (declarationInfo.declaration instanceof DefaultDeclaration) { delete alreadyImported.defaultAlias; - alreadyImported.defaultPurposal = declarationInfo.declaration.name; - } else { - alreadyImported.addSpecifier(declarationInfo.declaration.name); + alreadyImported.defaultAlias = declarationInfo.declaration.name; + } else if (!alreadyImported.specifiers.some(o => o.specifier === declarationInfo.declaration.name)) { + alreadyImported.specifiers.push(new SymbolSpecifier(declarationInfo.declaration.name)); } } else { - let imp: Import; + let imp: Import = new NamedImport(getRelativeLibraryName( + declarationInfo.from, + this.document.fileName, + ImportManager.rootPath, + )); + if (declarationInfo.declaration instanceof ModuleDeclaration) { imp = new NamespaceImport( declarationInfo.from, declarationInfo.declaration.name, ); } else if (declarationInfo.declaration instanceof DefaultDeclaration) { - imp = new ImportProxy(getRelativeLibraryName( - declarationInfo.from, - this.document.fileName, - ImportManager.rootPath, - )); - (imp as ImportProxy).defaultPurposal = declarationInfo.declaration.name; + (imp as NamedImport).defaultAlias = declarationInfo.declaration.name; } else { - imp = new ImportProxy(getRelativeLibraryName( - declarationInfo.from, - this.document.fileName, - ImportManager.rootPath, - )); - (imp as ImportProxy).specifiers.push(new SymbolSpecifier(declarationInfo.declaration.name)); + (imp as NamedImport).specifiers.push(new SymbolSpecifier(declarationInfo.declaration.name)); } this.imports.push(imp); this.addImportsToGroups([imp]); @@ -221,11 +223,11 @@ export class ImportManager implements ObjectManager { if (this._parsedDocument.nonLocalUsages.indexOf(actImport.alias) > -1) { keep.push(actImport); } - } else if (actImport instanceof ImportProxy) { + } else if (actImport instanceof NamedImport) { actImport.specifiers = actImport.specifiers .filter(o => this._parsedDocument.nonLocalUsages.indexOf(o.alias || o.specifier) > -1) .sort(specifierSort); - const defaultSpec = actImport.defaultAlias || actImport.defaultPurposal; + const defaultSpec = actImport.defaultAlias; if (actImport.specifiers.length || (!!defaultSpec && this._parsedDocument.nonLocalUsages.indexOf(defaultSpec) >= 0)) { keep.push(actImport); @@ -273,9 +275,6 @@ export class ImportManager implements ObjectManager { if (result) { delete this.organize; this._parsedDocument = await ImportManager.parser.parseSource(this.document.getText()); - this._parsedDocument.imports = this._parsedDocument.imports.map( - o => o instanceof NamedImport || o instanceof DefaultImport ? new ImportProxy(o) : o, - ); this.imports = this._parsedDocument.imports.map(o => o.clone()); for (const group of this.importGroups) { group.reset(); @@ -328,10 +327,14 @@ export class ImportManager implements ObjectManager { edits.push(TextEdit.delete(importRange(this.document, imp.start, imp.end))); } } - const actualDocumentsProxies = this._parsedDocument.imports.filter(o => o instanceof ImportProxy); + const actualDocumentsNamed = this._parsedDocument.imports.filter(o => o instanceof NamedImport); for (const imp of this.imports) { - if (imp instanceof ImportProxy && - actualDocumentsProxies.some((o: ImportProxy) => o.isEqual(imp as ImportProxy))) { + if (imp instanceof NamedImport && + actualDocumentsNamed.some((o: NamedImport) => + o.libraryName === imp.libraryName && + o.defaultAlias === imp.defaultAlias && + o.specifiers.length === imp.specifiers.length && + sameSpecifiers(o.specifiers, imp.specifiers))) { continue; } if (imp.isNew) { @@ -388,7 +391,7 @@ export class ImportManager implements ObjectManager { .reduce( (all, cur) => { let specifiers = all; - if (cur instanceof ImportProxy) { + if (cur instanceof NamedImport) { specifiers = specifiers.concat(cur.specifiers.map(o => o.alias || o.specifier)); if (cur.defaultAlias) { specifiers.push(cur.defaultAlias); @@ -399,7 +402,7 @@ export class ImportManager implements ObjectManager { } return specifiers; }, - [], + [] as string[], ); for (const decision of Object.keys( @@ -418,12 +421,17 @@ export class ImportManager implements ObjectManager { } } - const proxies = this.imports.filter(o => o instanceof ImportProxy) as ImportProxy[]; + const named = this.imports.filter(o => o instanceof NamedImport) as NamedImport[]; - for (const imp of proxies) { - if (imp.defaultPurposal && !imp.defaultAlias) { - imp.defaultAlias = await this.getDefaultIdentifier(imp.defaultPurposal); - delete imp.defaultPurposal; + for (const imp of named) { + if (imp.defaultAlias) { + const specifiers = getSpecifiers(); + if ( + specifiers.filter(o => o === imp.defaultAlias).length > 1 && + ImportManager.config.resolver.promptForSpecifiers + ) { + imp.defaultAlias = await this.getDefaultIdentifier(imp.defaultAlias); + } } for (const spec of imp.specifiers) { @@ -465,16 +473,13 @@ export class ImportManager implements ObjectManager { * @memberof ImportManager */ private async getDefaultIdentifier(declarationName: string): Promise { - if (!ImportManager.config.resolver.promptForSpecifiers) { - return declarationName; - } const result = await this.vscodeInputBox({ placeHolder: 'Default export name', - prompt: 'Please enter a variable name for the default export...', + prompt: 'Please enter an alias name for the default export...', validateInput: s => !!s ? '' : 'Please enter a variable name', value: declarationName, }); - return !!result ? result : undefined; + return !!result ? result.replace(/[,.-_]/g, '') : undefined; } /** diff --git a/src/extension/provider-items/document-structure/ImportsStructureTreeItem.ts b/src/extension/provider-items/document-structure/ImportsStructureTreeItem.ts index ce83229..26624eb 100644 --- a/src/extension/provider-items/document-structure/ImportsStructureTreeItem.ts +++ b/src/extension/provider-items/document-structure/ImportsStructureTreeItem.ts @@ -1,19 +1,11 @@ -import { - DefaultImport, - ExternalModuleImport, - Import, - NamedImport, - NamespaceImport, - Resource, - StringImport, -} from 'typescript-parser'; +import { ExternalModuleImport, Import, NamedImport, NamespaceImport, Resource, StringImport } from 'typescript-parser'; import { ExtensionContext, TreeItemCollapsibleState } from 'vscode'; import { BaseStructureTreeItem } from './BaseStructureTreeItem'; /** * Import specifier tree item that represents a specific (named) import of an import statement. - * + * * @export * @class ImportSpecifierStructureTreeItem * @extends {BaseStructureTreeItem} @@ -28,7 +20,7 @@ export class ImportSpecifierStructureTreeItem extends BaseStructureTreeItem { /** * Structure item that represents an import in a file. - * + * * @export * @class ImportStructureTreeItem * @extends {BaseStructureTreeItem} @@ -46,18 +38,21 @@ export class ImportStructureTreeItem extends BaseStructureTreeItem { public getChildren(): BaseStructureTreeItem[] { const imp = this.tsImport; - if (imp instanceof DefaultImport) { - return [new ImportSpecifierStructureTreeItem(imp.alias, imp, this.context)]; - } else if (imp instanceof ExternalModuleImport) { + if (imp instanceof ExternalModuleImport) { return [new ImportSpecifierStructureTreeItem(imp.alias, imp, this.context)]; } else if (imp instanceof NamedImport) { - return imp.specifiers.map( + const specifiers = imp.specifiers.map( s => new ImportSpecifierStructureTreeItem( `${s.specifier}${s.alias ? ` as ${s.alias}` : ''}`, imp, this.context, ), ); + if (imp.defaultAlias) { + specifiers.unshift(new ImportSpecifierStructureTreeItem(`(default) ${imp.defaultAlias}`, imp, this.context)); + } + + return specifiers; } else if (imp instanceof NamespaceImport) { return [new ImportSpecifierStructureTreeItem(imp.alias, imp, this.context)]; } @@ -68,7 +63,7 @@ export class ImportStructureTreeItem extends BaseStructureTreeItem { /** * Structure item that contains all imports from the file. * Collapsed by default. - * + * * @export * @class ImportsStructureTreeItem * @extends {BaseStructureTreeItem} diff --git a/src/extension/proxy-objects/ImportProxy.ts b/src/extension/proxy-objects/ImportProxy.ts deleted file mode 100644 index 9c07b89..0000000 --- a/src/extension/proxy-objects/ImportProxy.ts +++ /dev/null @@ -1,90 +0,0 @@ -import { DefaultImport, NamedImport, SymbolSpecifier } from 'typescript-parser'; - -/** - * Proxy class that wraps a NamedImport or a DefaultImport. Is used by the DocumentController to - * determine if a default import or a named import is used. - * - * @export - * @class ImportProxy - * @extends {NamedImport} - */ -export class ImportProxy extends NamedImport { - public defaultPurposal: string; - public defaultAlias: string | undefined; - - constructor(library: NamedImport | DefaultImport | string, start?: number, end?: number) { - super(typeof library !== 'string' ? library.libraryName : library, start, end); - - if (typeof library !== 'string') { - this.start = library.start; - this.end = library.end; - if (library instanceof NamedImport) { - this.specifiers = library.specifiers; - const defaultSpec = this.specifiers.find(o => o.specifier === 'default'); - if (defaultSpec) { - this.specifiers.splice(this.specifiers.indexOf(defaultSpec), 1); - this.defaultAlias = defaultSpec.alias; - } - } else { - this.defaultAlias = library.alias; - } - } - } - - /** - * Adds a specifier to the import. - * - * @param {string} name - * - * @memberof ImportProxy - */ - public addSpecifier(name: string): void { - if (!this.specifiers.some(o => o.specifier === name)) { - this.specifiers.push(new SymbolSpecifier(name)); - } - } - - /** - * Clone this proxy. - * - * @returns {ImportProxy} - * - * @memberof ImportProxy - */ - public clone(): ImportProxy { - const clone = new ImportProxy(this.libraryName, this.start, this.end); - clone.specifiers = this.specifiers.map(o => o.clone()); - clone.defaultAlias = this.defaultAlias; - clone.defaultPurposal = this.defaultPurposal; - return clone; - } - - /** - * Does check for equality to another proxy. All properties are checked and as a last step, - * the specifiers are (with order in mind) checked. - * - * @param {ImportProxy} imp - * @returns {boolean} - * - * @memberof ImportProxy - */ - public isEqual(imp: ImportProxy): boolean { - const sameSpecifiers = (specs1: SymbolSpecifier[], specs2: SymbolSpecifier[]) => { - for (const spec of specs1) { - const spec2 = specs2[specs1.indexOf(spec)]; - if (!spec2 || - spec.specifier !== spec2.specifier || - spec.alias !== spec2.alias) { - return false; - } - } - return true; - }; - - return this.libraryName === imp.libraryName && - this.defaultAlias === imp.defaultAlias && - this.defaultPurposal === imp.defaultPurposal && - this.specifiers.length === imp.specifiers.length && - sameSpecifiers(this.specifiers, imp.specifiers); - } -} diff --git a/test/extension/extensions/DocumentSymbolStructureExtension.test.ts b/test/extension/extensions/DocumentSymbolStructureExtension.test.ts index a94faf8..817bd95 100644 --- a/test/extension/extensions/DocumentSymbolStructureExtension.test.ts +++ b/test/extension/extensions/DocumentSymbolStructureExtension.test.ts @@ -24,16 +24,12 @@ const rootPath = Container.get(iocSymbols.rootPath); describe('DocumentSymbolStructureExtension', () => { let extension: DocumentSymbolStructureExtension; - let document: vscode.TextDocument; + const file = join( + rootPath, + 'extension/extensions/documentSymbolStructureExtension/documentSymbolFile.ts', + ); before(async () => { - const file = join( - rootPath, - 'extension/extensions/documentSymbolStructureExtension/documentSymbolFile.ts', - ); - document = await vscode.workspace.openTextDocument(file); - await vscode.window.showTextDocument(document); - const ctx = Container.get(iocSymbols.extensionContext); const logger = Container.get(iocSymbols.loggerFactory); const parser = Container.get(iocSymbols.typescriptParser); @@ -42,15 +38,20 @@ describe('DocumentSymbolStructureExtension', () => { extension = new DocumentSymbolStructureExtension(ctx, logger, config, parser); }); + beforeEach(async () => { + const document = await vscode.workspace.openTextDocument(file); + await vscode.window.showTextDocument(document); + }); + + afterEach(async () => { + await vscode.commands.executeCommand('workbench.action.closeAllEditors'); + }); + it.skip('should return an empty array if no active window is set', async () => { - try { - await vscode.commands.executeCommand('workbench.action.closeAllEditors'); + await vscode.commands.executeCommand('workbench.action.closeAllEditors'); - const elements = await extension.getChildren() as BaseStructureTreeItem[]; - elements.should.have.lengthOf(0); - } finally { - await vscode.window.showTextDocument(document); - } + const elements = await extension.getChildren() as BaseStructureTreeItem[]; + elements.should.have.lengthOf(0); }); it('should return a "file not parsable" if it is no ts file', async () => { @@ -66,7 +67,6 @@ describe('DocumentSymbolStructureExtension', () => { elements[0].should.be.instanceof(NotParseableStructureTreeItem); await vscode.commands.executeCommand('workbench.action.closeAllEditors'); - await vscode.window.showTextDocument(document); }); it('should return a "not enabled" if the part is disabled via config', async () => { diff --git a/test/extension/managers/ImportManager.test.ts b/test/extension/managers/ImportManager.test.ts index 8135634..04c1250 100644 --- a/test/extension/managers/ImportManager.test.ts +++ b/test/extension/managers/ImportManager.test.ts @@ -2,14 +2,13 @@ import * as chai from 'chai'; import { join } from 'path'; import * as sinon from 'sinon'; import sinonChai = require('sinon-chai'); -import { DeclarationIndex, File } from 'typescript-parser'; +import { DeclarationIndex, File, NamedImport } from 'typescript-parser'; import { Position, Range, TextDocument, window, workspace } from 'vscode'; import { findFiles } from '../../../src/extension/extensions/ImportResolveExtension'; import { Container } from '../../../src/extension/IoC'; import { iocSymbols } from '../../../src/extension/IoCSymbols'; import { ImportManager } from '../../../src/extension/managers'; -import { ImportProxy } from '../../../src/extension/proxy-objects/ImportProxy'; import { VscodeExtensionConfig } from '../../../src/extension/VscodeExtensionConfig'; const should = chai.should(); @@ -86,7 +85,7 @@ describe('ImportManager', () => { const ctrl = await ImportManager.create(document); const imps = (ctrl as any).parsedDocument.imports; - imps[0].should.be.an.instanceof(ImportProxy); + imps[0].should.be.an.instanceof(NamedImport); should.not.exist(imps[0].defaultAlias); }); @@ -104,7 +103,7 @@ describe('ImportManager', () => { const ctrl = await ImportManager.create(document); const imps = (ctrl as any).parsedDocument.imports; - imps[0].should.be.an.instanceof(ImportProxy); + imps[0].should.be.an.instanceof(NamedImport); imps[0].defaultAlias.should.equal('myDefaultExportedFunction'); }); @@ -119,9 +118,9 @@ describe('ImportManager', () => { const ctrl = await ImportManager.create(document); const imps = (ctrl as any).parsedDocument.imports; - imps[0].should.be.an.instanceof(ImportProxy); + imps[0].should.be.an.instanceof(NamedImport); imps[0].defaultAlias.should.equal('myDefaultExportedFunction'); - imps[1].should.be.an.instanceof(ImportProxy); + imps[1].should.be.an.instanceof(NamedImport); should.not.exist(imps[1].defaultAlias); }); @@ -140,7 +139,7 @@ describe('ImportManager', () => { const imps = (ctrl as any).parsedDocument.imports; imps.should.have.lengthOf(1); - imps[0].should.not.be.an.instanceof(ImportProxy); + imps[0].should.not.be.an.instanceof(NamedImport); }); it('should not add a proxy for an external import', async () => { @@ -158,7 +157,7 @@ describe('ImportManager', () => { const imps = (ctrl as any).parsedDocument.imports; imps.should.have.lengthOf(1); - imps[0].should.not.be.an.instanceof(ImportProxy); + imps[0].should.not.be.an.instanceof(NamedImport); }); it('should not add a proxy for a string import', async () => { @@ -176,7 +175,7 @@ describe('ImportManager', () => { const imps = (ctrl as any).parsedDocument.imports; imps.should.have.lengthOf(1); - imps[0].should.not.be.an.instanceof(ImportProxy); + imps[0].should.not.be.an.instanceof(NamedImport); }); }); @@ -200,7 +199,7 @@ describe('ImportManager', () => { (ctrl as any).imports.should.have.lengthOf(2); (ctrl as any).imports[1].libraryName.should.equal('body-parser'); - (ctrl as any).imports[1].should.not.be.an.instanceof(ImportProxy); + (ctrl as any).imports[1].should.not.be.an.instanceof(NamedImport); }); it('should add a default import to the import index.', async () => { @@ -214,8 +213,7 @@ describe('ImportManager', () => { (ctrl as any).imports[1].libraryName.should.equal( '../../server/indices/defaultExport/lateDefaultExportedElement', ); - (ctrl as any).imports[1].defaultPurposal.should.equal('myDefaultExportedFunction'); - should.not.exist((ctrl as any).imports[1].defaultAlias); + (ctrl as any).imports[1].defaultAlias.should.equal('myDefaultExportedFunction'); }); it('should add multiple imports to the import index', async () => { @@ -634,9 +632,9 @@ describe('ImportManager', () => { ctrl.addDeclarationImport(declaration!); (await ctrl.commit()).should.be.true; - stub.should.be.calledWithMatch({ value: 'myDefaultExportedFunction' }); + stub.should.not.be.called; document.lineAt(0).text.should.equals( - `import DEFAULT_IMPORT from '../../server/indices/defaultExport/lateDefaultExportedElement';`, + `import myDefaultExportedFunction from '../../server/indices/defaultExport/lateDefaultExportedElement';`, ); } finally { restoreInputBox(stub); @@ -698,7 +696,7 @@ describe('ImportManager', () => { (await ctrl.commit()).should.be.true; document.lineAt(0).text.should.equals( - `import { default as DEFAULT_IMPORT, MultiExportClass } ` + + `import multiExport, { MultiExportClass } ` + `from '../../server/indices/defaultExport/multiExport';`, ); } finally { @@ -729,14 +727,14 @@ describe('ImportManager', () => { await ctrl.addDeclarationImport(declaration!).commit(); document.lineAt(0).text.should.equals( - `import DEFAULT_IMPORT from '../../server/indices/defaultExport/multiExport';`, + `import multiExport from '../../server/indices/defaultExport/multiExport';`, ); declaration = index.declarationInfos.find(o => o.declaration.name === 'MultiExportClass'); await ctrl.addDeclarationImport(declaration!).commit(); document.lineAt(0).text.should.equals( - `import { default as DEFAULT_IMPORT, MultiExportClass } ` + + `import multiExport, { MultiExportClass } ` + `from '../../server/indices/defaultExport/multiExport';`, ); } finally { @@ -760,7 +758,7 @@ describe('ImportManager', () => { await ctrl.commit(); document.lineAt(0).text.should.equals( - `import { default as DEFAULT_IMPORT, MultiExportClass } ` + + `import multiExport, { MultiExportClass } ` + `from '../../server/indices/defaultExport/multiExport';`, ); } finally { diff --git a/test/extension/proxy-objects/ImportProxy.test.ts b/test/extension/proxy-objects/ImportProxy.test.ts deleted file mode 100644 index d7cec5b..0000000 --- a/test/extension/proxy-objects/ImportProxy.test.ts +++ /dev/null @@ -1,247 +0,0 @@ -import * as chai from 'chai'; -import { given } from 'mocha-testdata'; -import { - DefaultImport, - GENERATORS, - NamedImport, - SymbolSpecifier, - TypescriptCodeGenerator, - TypescriptGenerationOptions, -} from 'typescript-parser'; - -import { ImportProxy } from '../../../src/extension/proxy-objects/ImportProxy'; - -chai.should(); - -describe('ImportProxy', () => { - - describe('constructor()', () => { - - it('should create a descendent of a TsNamedImport', () => { - const proxy = new ImportProxy('foo'); - - proxy.should.be.an.instanceof(ImportProxy); - proxy.libraryName.should.equal('foo'); - }); - - it('should use the values of a given TsNamedImport', () => { - const imp = new NamedImport('foo', 42, 1337); - const proxy = new ImportProxy(imp); - - proxy.libraryName.should.equal(imp.libraryName); - proxy.start!.should.equal(imp.start); - proxy.end!.should.equal(imp.end); - }); - - it('should duplicate the specifiers of a TsNamedImport', () => { - const imp = new NamedImport('foo'); - imp.specifiers.push(new SymbolSpecifier('bar')); - - const proxy = new ImportProxy(imp); - proxy.specifiers.should.be.an('array').with.lengthOf(1); - proxy.specifiers[0].specifier.should.equal('bar'); - }); - - it('should add a default alias from a TsDefaultImport', () => { - const imp = new DefaultImport('foo', 'ALIAS'); - const proxy = new ImportProxy(imp); - - proxy.defaultAlias!.should.equal('ALIAS'); - }); - - }); - - describe('addSpecifier()', () => { - - let proxy: ImportProxy; - - beforeEach(() => { - proxy = new ImportProxy('foo'); - }); - - it('should add a specifier to the list', () => { - proxy.addSpecifier('bar'); - proxy.specifiers.should.have.lengthOf(1); - proxy.specifiers[0].specifier.should.equal('bar'); - }); - - it('should not add a specifier if it already exists', () => { - proxy.addSpecifier('bar'); - proxy.specifiers.should.have.lengthOf(1); - proxy.addSpecifier('bar'); - proxy.specifiers.should.have.lengthOf(1); - }); - - }); - - describe('clone()', () => { - - it('should clone the whole ImportProxy element', () => { - const p1 = new ImportProxy('foo'); - p1.addSpecifier('bar'); - p1.defaultAlias = 'ALIAS'; - - const p2 = p1.clone(); - - (p1.isEqual(p2)).should.be.true; - }); - - }); - - describe('isEqual()', () => { - - it('should return true if another proxy is equal', () => { - const p1 = new ImportProxy('foo'); - const p2 = new ImportProxy('foo'); - - p1.addSpecifier('bar'); - p2.addSpecifier('bar'); - - p1.addSpecifier('baz'); - p2.addSpecifier('baz'); - - (p1.isEqual(p2)).should.be.true; - }); - - given( - { - description: 'foo vs bar', - p1: new ImportProxy('foo'), - p2: new ImportProxy('bar'), - }, - { - description: 'foo with different alias', - p1: (() => { - const p = new ImportProxy('foo'); - p.defaultAlias = 'ALIAS'; - return p; - })(), - p2: (() => { - const p = new ImportProxy('foo'); - p.defaultAlias = 'ALIAS_2'; - return p; - })(), - }, - { - description: 'foo with different default export', - p1: (() => { - const p = new ImportProxy('foo'); - p.defaultPurposal = 'MyDefaultExport'; - return p; - })(), - p2: (() => { - const p = new ImportProxy('foo'); - p.defaultPurposal = 'MyDefaultExport_2'; - return p; - })(), - }, - { - description: 'foo with different specifiers count', - p1: (() => { - const p = new ImportProxy('foo'); - p.addSpecifier('bar'); - p.addSpecifier('baz'); - return p; - })(), - p2: (() => { - const p = new ImportProxy('foo'); - p.addSpecifier('bar'); - return p; - })(), - }, - { - description: 'foo with different specifiers', - p1: (() => { - const p = new ImportProxy('foo'); - p.addSpecifier('baz'); - return p; - })(), - p2: (() => { - const p = new ImportProxy('foo'); - p.addSpecifier('bar'); - return p; - })(), - }, - ).it('should return false if another proxy is not equal', ({ p1, p2 }) => { - (p1.isEqual(p2)).should.be.false; - }); - - }); - - describe('toImport()', () => { - - let generator: TypescriptCodeGenerator; - - const options: TypescriptGenerationOptions = { - eol: ';', - multiLineWrapThreshold: 120, - multiLineTrailingComma: false, - stringQuoteStyle: `'`, - spaceBraces: true, - tabSize: 4, - }; - let proxy: ImportProxy; - - before(() => { - GENERATORS[ImportProxy.name] = (proxy: ImportProxy) => { - if (proxy.specifiers.length <= 0 && (proxy.defaultAlias || proxy.defaultPurposal)) { - return generator.generate( - new DefaultImport( - proxy.libraryName, (proxy.defaultAlias || proxy.defaultPurposal)!, proxy.start, proxy.end, - ), - ); - } - if (proxy.defaultAlias) { - proxy.specifiers.push(new SymbolSpecifier('default', proxy.defaultAlias)); - } - const named = new NamedImport( - proxy.libraryName, proxy.start, proxy.end, - ); - named.specifiers = proxy.specifiers; - return generator.generate(named); - }; - }); - - beforeEach(() => { - generator = new TypescriptCodeGenerator(options); - proxy = new ImportProxy('foo'); - }); - - it('should generate a TsDefaultImport when no specifiers are provided', () => { - proxy.defaultAlias = 'ALIAS'; - generator.generate(proxy).should.equal(`import ALIAS from 'foo';`); - }); - - it('should generate a normal TsNamedImport when no default import is provided', () => { - proxy.addSpecifier('bar'); - proxy.addSpecifier('baz'); - generator.generate(proxy).should.equal(`import { bar, baz } from 'foo';`); - }); - - it('should generate a normal TsNamedImport with aliases when no default import is provided', () => { - proxy.addSpecifier('bar'); - proxy.specifiers.push(new SymbolSpecifier('baz', 'blub')); - generator.generate(proxy).should.equal(`import { bar, baz as blub } from 'foo';`); - }); - - it('should generate a TsNamedImport with default import', () => { - proxy.defaultAlias = 'ALIAS'; - proxy.addSpecifier('bar'); - generator.generate(proxy).should.equal(`import { bar, default as ALIAS } from 'foo';`); - }); - - it('should omit semicolons if configured', () => { - const optionsClone = Object.assign({}, options); - optionsClone.eol = ''; - generator = new TypescriptCodeGenerator(optionsClone); - proxy.defaultAlias = 'ALIAS'; - generator.generate(proxy).should.equal(`import ALIAS from 'foo'`); - }); - - it('should generate an empty named import if no specifiers and no default is set', () => { - generator.generate(proxy).should.equal(`import { } from 'foo';`); - }); - - }); - -}); diff --git a/tslint.json b/tslint.json index 7f754bc..bd1ced0 100644 --- a/tslint.json +++ b/tslint.json @@ -30,13 +30,12 @@ } ], "strict-boolean-expressions": false, - "ter-indent": [ + "indent": [ true, - 4, - { - "SwitchCase": 1 - } + "spaces", + 4 ], + "ter-indent": false, "typedef": [ true, "call-signature", diff --git a/yarn.lock b/yarn.lock index 7718b81..8dff7d6 100644 --- a/yarn.lock +++ b/yarn.lock @@ -25,13 +25,17 @@ version "1.0.0" resolved "https://registry.yarnpkg.com/@semantic-release/error/-/error-1.0.0.tgz#bb8f8eeedd5c7f8c46f96b37ef39e1b8c376c1cc" -"@semantic-release/last-release-npm@^1.2.1": - version "1.2.1" - resolved "https://registry.yarnpkg.com/@semantic-release/last-release-npm/-/last-release-npm-1.2.1.tgz#ff748142ecf15354b833a86ba18205f7fce594ee" +"@semantic-release/error@^2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@semantic-release/error/-/error-2.0.0.tgz#f156ecd509f5288c48bc7425a8abe22f975d1f8b" + +"@semantic-release/last-release-npm@^2.0.0": + version "2.0.1" + resolved "https://registry.yarnpkg.com/@semantic-release/last-release-npm/-/last-release-npm-2.0.1.tgz#9d9e40b7dfa2778eb08dc995263da3e366542416" dependencies: - "@semantic-release/error" "^1.0.0" - npm-registry-client "^7.0.1" - npmlog "^1.2.1" + "@semantic-release/error" "^2.0.0" + npm-registry-client "^8.4.0" + npmlog "^4.0.0" "@semantic-release/release-notes-generator@^4.0.0": version "4.0.1" @@ -52,9 +56,9 @@ version "2.2.43" resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-2.2.43.tgz#03c54589c43ad048cbcbfd63999b55d0424eec27" -"@types/node@^8.0.28": - version "8.0.28" - resolved "https://registry.yarnpkg.com/@types/node/-/node-8.0.28.tgz#86206716f8d9251cf41692e384264cbd7058ad60" +"@types/node@^8.0.31": + version "8.0.31" + resolved "https://registry.yarnpkg.com/@types/node/-/node-8.0.31.tgz#d9af61093cf4bfc9f066ca34de0175012cfb0ce9" "@types/reflect-metadata@0.0.5": version "0.0.5" @@ -67,10 +71,14 @@ "@types/chai" "*" "@types/sinon" "*" -"@types/sinon@*", "@types/sinon@^2.3.4": +"@types/sinon@*": version "2.3.4" resolved "https://registry.yarnpkg.com/@types/sinon/-/sinon-2.3.4.tgz#2b3aa82dfc791eeff1d970b657a77eafff2899ff" +"@types/sinon@^2.3.5": + version "2.3.5" + resolved "https://registry.yarnpkg.com/@types/sinon/-/sinon-2.3.5.tgz#68f1e0ac15f2eb6cc682b7af87cd517acc77b589" + JSONStream@^1.0.4: version "1.3.1" resolved "https://registry.yarnpkg.com/JSONStream/-/JSONStream-1.3.1.tgz#707f761e01dae9e16f1bcf93703b78c70966579a" @@ -132,21 +140,10 @@ ansi-styles@^3.1.0: dependencies: color-convert "^1.9.0" -ansi@^0.3.0, ansi@~0.3.0: - version "0.3.1" - resolved "https://registry.yarnpkg.com/ansi/-/ansi-0.3.1.tgz#0c42d4fb17160d5a9af1e484bace1c66922c1b21" - aproba@^1.0.3: version "1.1.2" resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.1.2.tgz#45c6629094de4e96f693ef7eab74ae079c240fc1" -are-we-there-yet@~1.0.0: - version "1.0.6" - resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-1.0.6.tgz#a2d28c93102aa6cc96245a26cb954de06ec53f0c" - dependencies: - delegates "^1.0.0" - readable-stream "^2.0.0 || ^1.1.13" - are-we-there-yet@~1.1.2: version "1.1.4" resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-1.1.4.tgz#bb5dca382bb94f05e15194373d16fd3ba1ca110d" @@ -200,10 +197,6 @@ arrify@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" -asap@^2.0.0: - version "2.0.6" - resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46" - asn1@~0.2.3: version "0.2.3" resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.3.tgz#dac8787713c9966849fc8180777ebe9c1ddf3b86" @@ -328,6 +321,10 @@ builtin-modules@^1.0.0: version "1.1.1" resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-1.1.1.tgz#270f076c5a72c02f5b65a47df94c5fe3a278892f" +builtins@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/builtins/-/builtins-1.0.3.tgz#cb94faeb61c8696451db36534e1422f94f0aee88" + camelcase-keys@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/camelcase-keys/-/camelcase-keys-2.1.0.tgz#308beeaffdf28119051efa1d932213c91b8f92e7" @@ -585,9 +582,9 @@ core-util-is@1.0.2, core-util-is@^1.0.1, core-util-is@~1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" -coveralls@^2.13.1: - version "2.13.1" - resolved "https://registry.yarnpkg.com/coveralls/-/coveralls-2.13.1.tgz#d70bb9acc1835ec4f063ff9dac5423c17b11f178" +coveralls@^2.13.3: + version "2.13.3" + resolved "https://registry.yarnpkg.com/coveralls/-/coveralls-2.13.3.tgz#9ad7c2ae527417f361e8b626483f48ee92dd2bc7" dependencies: js-yaml "3.6.1" lcov-parse "0.0.10" @@ -701,13 +698,6 @@ delegates@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" -dezalgo@^1.0.1: - version "1.0.3" - resolved "https://registry.yarnpkg.com/dezalgo/-/dezalgo-1.0.3.tgz#7f742de066fc748bc8db820569dddce49bf0d456" - dependencies: - asap "^2.0.0" - wrappy "1" - diff@3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/diff/-/diff-3.2.0.tgz#c9ce393a4b7cbd0b058a725c93df299027868ff9" @@ -816,6 +806,18 @@ execa@^0.7.0: signal-exit "^3.0.0" strip-eof "^1.0.0" +execa@^0.8.0: + version "0.8.0" + resolved "https://registry.yarnpkg.com/execa/-/execa-0.8.0.tgz#d8d76bbc1b55217ed190fd6dd49d3c774ecfc8da" + dependencies: + cross-spawn "^5.0.1" + get-stream "^3.0.0" + is-stream "^1.1.0" + npm-run-path "^2.0.0" + p-finally "^1.0.0" + signal-exit "^3.0.0" + strip-eof "^1.0.0" + expand-brackets@^0.1.4: version "0.1.5" resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-0.1.5.tgz#df07284e342a807cd733ac5af72411e581d1177b" @@ -959,6 +961,14 @@ from@~0: version "0.1.7" resolved "https://registry.yarnpkg.com/from/-/from-0.1.7.tgz#83c60afc58b9c56997007ed1a768b3ab303a44fe" +fs-extra@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-4.0.2.tgz#f91704c53d1b461f893452b0c307d9997647ab6b" + dependencies: + graceful-fs "^4.1.2" + jsonfile "^4.0.0" + universalify "^0.1.0" + fs.realpath@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" @@ -972,16 +982,6 @@ fstream@^1.0.2: mkdirp ">=0.5 0" rimraf "2" -gauge@~1.2.0: - version "1.2.7" - resolved "https://registry.yarnpkg.com/gauge/-/gauge-1.2.7.tgz#e9cec5483d3d4ee0ef44b60a7d99e4935e136d93" - dependencies: - ansi "^0.3.0" - has-unicode "^2.0.0" - lodash.pad "^4.1.0" - lodash.padend "^4.1.0" - lodash.padstart "^4.1.0" - gauge@~2.7.3: version "2.7.4" resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7" @@ -1077,9 +1077,9 @@ gitconfiglocal@^1.0.0: dependencies: ini "^1.3.2" -github@^8.0.0: - version "8.2.1" - resolved "https://registry.yarnpkg.com/github/-/github-8.2.1.tgz#616b2211fbcd1cc8631669aed67653e62eb53816" +github@^11.0.0: + version "11.0.0" + resolved "https://registry.yarnpkg.com/github/-/github-11.0.0.tgz#edb32df5efb33cad004ebf0bdd2a4b30bb63a854" dependencies: follow-redirects "0.0.7" https-proxy-agent "^1.0.0" @@ -1373,7 +1373,7 @@ hoek@2.x.x: version "2.16.3" resolved "https://registry.yarnpkg.com/hoek/-/hoek-2.16.3.tgz#20bb7403d3cea398e91dc4710a8ff1b8274a25ed" -hosted-git-info@^2.1.4, hosted-git-info@^2.1.5: +hosted-git-info@^2.1.4, hosted-git-info@^2.4.2: version "2.5.0" resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.5.0.tgz#6d60e34b3abbc8313062c3b798ef8d901a07af3c" @@ -1656,6 +1656,12 @@ json3@3.3.2: version "3.3.2" resolved "https://registry.yarnpkg.com/json3/-/json3-3.3.2.tgz#3c0434743df93e2f5c42aee7b19bcb483575f4e1" +jsonfile@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb" + optionalDependencies: + graceful-fs "^4.1.6" + jsonify@~0.0.0: version "0.0.0" resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.0.tgz#2c74b6ee41d93ca51b7b5aaee8f503631d252a73" @@ -1828,18 +1834,6 @@ lodash.keys@^3.0.0: lodash.isarguments "^3.0.0" lodash.isarray "^3.0.0" -lodash.pad@^4.1.0: - version "4.5.1" - resolved "https://registry.yarnpkg.com/lodash.pad/-/lodash.pad-4.5.1.tgz#4330949a833a7c8da22cc20f6a26c4d59debba70" - -lodash.padend@^4.1.0: - version "4.6.1" - resolved "https://registry.yarnpkg.com/lodash.padend/-/lodash.padend-4.6.1.tgz#53ccba047d06e158d311f45da625f4e49e6f166e" - -lodash.padstart@^4.1.0: - version "4.6.1" - resolved "https://registry.yarnpkg.com/lodash.padstart/-/lodash.padstart-4.6.1.tgz#d2e3eebff0d9d39ad50f5cbd1b52a7bce6bb611b" - lodash.restparam@^3.0.0: version "3.6.1" resolved "https://registry.yarnpkg.com/lodash.restparam/-/lodash.restparam-3.6.1.tgz#936a4e309ef330a7645ed4145986c85ae5b20805" @@ -2111,26 +2105,29 @@ normalize-path@^2.0.1: dependencies: remove-trailing-separator "^1.0.1" -"npm-package-arg@^3.0.0 || ^4.0.0": - version "4.2.1" - resolved "https://registry.yarnpkg.com/npm-package-arg/-/npm-package-arg-4.2.1.tgz#593303fdea85f7c422775f17f9eb7670f680e3ec" +"npm-package-arg@^3.0.0 || ^4.0.0 || ^5.0.0": + version "5.1.2" + resolved "https://registry.yarnpkg.com/npm-package-arg/-/npm-package-arg-5.1.2.tgz#fb18d17bb61e60900d6312619919bd753755ab37" dependencies: - hosted-git-info "^2.1.5" + hosted-git-info "^2.4.2" + osenv "^0.1.4" semver "^5.1.0" + validate-npm-package-name "^3.0.0" -npm-registry-client@^7.0.1: - version "7.5.0" - resolved "https://registry.yarnpkg.com/npm-registry-client/-/npm-registry-client-7.5.0.tgz#0f6dd6e5d11424cfa99fce5b930feaf09b4f7f04" +npm-registry-client@^8.4.0: + version "8.5.0" + resolved "https://registry.yarnpkg.com/npm-registry-client/-/npm-registry-client-8.5.0.tgz#4878fb6fa1f18a5dc08ae83acf94d0d0112d7ed0" dependencies: concat-stream "^1.5.2" graceful-fs "^4.1.6" normalize-package-data "~1.0.1 || ^2.0.0" - npm-package-arg "^3.0.0 || ^4.0.0" + npm-package-arg "^3.0.0 || ^4.0.0 || ^5.0.0" once "^1.3.3" request "^2.74.0" retry "^0.10.0" semver "2 >=2.2.1 || 3.x || 4 || 5" slide "^1.1.3" + ssri "^4.1.2" optionalDependencies: npmlog "2 || ^3.1.0 || ^4.0.0" @@ -2163,14 +2160,6 @@ npmconf@^2.1.2: gauge "~2.7.3" set-blocking "~2.0.0" -npmlog@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-1.2.1.tgz#28e7be619609b53f7ad1dd300a10d64d716268b6" - dependencies: - ansi "~0.3.0" - are-we-there-yet "~1.0.0" - gauge "~1.2.0" - number-is-nan@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" @@ -2243,6 +2232,16 @@ p-map@^1.1.1: version "1.2.0" resolved "https://registry.yarnpkg.com/p-map/-/p-map-1.2.0.tgz#e4e94f311eabbc8633a1e79908165fca26241b6b" +p-reduce@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/p-reduce/-/p-reduce-1.0.0.tgz#18c2b0dd936a4690a529f8231f58a0fdb6a47dfa" + +p-series@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/p-series/-/p-series-1.0.0.tgz#7ec9e7b4406cc32066298a6f9860e55e91b36e07" + dependencies: + p-reduce "^1.0.0" + package-json@^4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/package-json/-/package-json-4.0.1.tgz#8869a0401253661c4c4ca3da6c2121ed555f5eed" @@ -2444,7 +2443,7 @@ read-pkg@^1.0.0, read-pkg@^1.1.0: isarray "0.0.1" string_decoder "~0.10.x" -readable-stream@^2.0.0, "readable-stream@^2.0.0 || ^1.1.13", readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.4, readable-stream@^2.0.5, readable-stream@^2.0.6, readable-stream@^2.1.5, readable-stream@^2.2.2: +readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.4, readable-stream@^2.0.5, readable-stream@^2.0.6, readable-stream@^2.1.5, readable-stream@^2.2.2: version "2.3.3" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.3.tgz#368f2512d79f9d46fdfc71349ae7878bbc1eb95c" dependencies: @@ -2644,17 +2643,7 @@ rimraf@2, rimraf@^2.2.8: dependencies: glob "^7.0.5" -run-auto@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/run-auto/-/run-auto-2.0.0.tgz#5f4353f58adbd6b74926489b4f259e1dad6a78d6" - dependencies: - dezalgo "^1.0.1" - -run-series@^1.1.3: - version "1.1.4" - resolved "https://registry.yarnpkg.com/run-series/-/run-series-1.1.4.tgz#89a73ddc5e75c9ef8ab6320c0a1600d6a41179b9" - -safe-buffer@^5.0.1, safe-buffer@~5.1.0, safe-buffer@~5.1.1: +safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@~5.1.0, safe-buffer@~5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.1.tgz#893312af69b2123def71f57889001671eeb2c853" @@ -2670,28 +2659,29 @@ semantic-release-visualstudio-marketplace-version@^1.0.0: lodash.get "^4.4.2" request "^2.79.0" -semantic-release@^8.0.0: - version "8.0.1" - resolved "https://registry.yarnpkg.com/semantic-release/-/semantic-release-8.0.1.tgz#f04fb562faf1acc275d6d756730ee6d1afbdc47e" +semantic-release@^8.0.3: + version "8.1.0" + resolved "https://registry.yarnpkg.com/semantic-release/-/semantic-release-8.1.0.tgz#67483049656664ce54787c8c51a4b9a86b81c6ec" dependencies: "@semantic-release/commit-analyzer" "^3.0.1" "@semantic-release/condition-travis" "^6.0.0" - "@semantic-release/error" "^1.0.0" - "@semantic-release/last-release-npm" "^1.2.1" + "@semantic-release/error" "^2.0.0" + "@semantic-release/last-release-npm" "^2.0.0" "@semantic-release/release-notes-generator" "^4.0.0" + execa "^0.8.0" + fs-extra "^4.0.2" git-head "^1.2.1" - github "^8.0.0" + github "^11.0.0" lodash "^4.0.0" nerf-dart "^1.0.0" nopt "^4.0.0" normalize-package-data "^2.3.4" npmconf "^2.1.2" npmlog "^4.0.0" + p-series "^1.0.0" parse-github-repo-url "^1.3.0" require-relative "^0.8.7" - run-auto "^2.0.0" - run-series "^1.1.3" - semver "^5.2.0" + semver "^5.4.1" semver-diff@^2.0.0: version "2.1.0" @@ -2699,7 +2689,7 @@ semver-diff@^2.0.0: dependencies: semver "^5.0.3" -"semver@2 >=2.2.1 || 3.x || 4 || 5", "semver@2 || 3 || 4 || 5", semver@^5.0.1, semver@^5.0.3, semver@^5.1.0, semver@^5.2.0, semver@^5.3.0, semver@^5.4.1: +"semver@2 >=2.2.1 || 3.x || 4 || 5", "semver@2 || 3 || 4 || 5", semver@^5.0.1, semver@^5.0.3, semver@^5.1.0, semver@^5.3.0, semver@^5.4.1: version "5.4.1" resolved "https://registry.yarnpkg.com/semver/-/semver-5.4.1.tgz#e059c09d8571f0540823733433505d3a2f00b18e" @@ -2729,11 +2719,11 @@ signal-exit@^3.0.0, signal-exit@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d" -sinon-chai@^2.13.0: - version "2.13.0" - resolved "https://registry.yarnpkg.com/sinon-chai/-/sinon-chai-2.13.0.tgz#b9a42e801c20234bfc2f43b29e6f4f61b60990c4" +sinon-chai@^2.14.0: + version "2.14.0" + resolved "https://registry.yarnpkg.com/sinon-chai/-/sinon-chai-2.14.0.tgz#da7dd4cc83cd6a260b67cca0f7a9fdae26a1205d" -sinon@4.0.0: +sinon@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/sinon/-/sinon-4.0.0.tgz#a54a5f0237aa1dd2215e5e81c89b42b50c4fdb6b" dependencies: @@ -2832,6 +2822,12 @@ sshpk@^1.7.0: jsbn "~0.1.0" tweetnacl "~0.14.0" +ssri@^4.1.2: + version "4.1.6" + resolved "https://registry.yarnpkg.com/ssri/-/ssri-4.1.6.tgz#0cb49b6ac84457e7bdd466cb730c3cb623e9a25b" + dependencies: + safe-buffer "^5.1.0" + stat-mode@^0.2.0: version "0.2.2" resolved "https://registry.yarnpkg.com/stat-mode/-/stat-mode-0.2.2.tgz#e6c80b623123d7d80cf132ce538f346289072502" @@ -3040,7 +3036,7 @@ tslib@^1.0.0, tslib@^1.7.1: version "1.7.1" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.7.1.tgz#bc8004164691923a79fe8378bbeb3da2017538ec" -tslint-config-airbnb@^5.3.0-beta: +tslint-config-airbnb@^5.3.0: version "5.3.0" resolved "https://registry.yarnpkg.com/tslint-config-airbnb/-/tslint-config-airbnb-5.3.0.tgz#78c3e6fcc452eb2a460266004f85a201a0a5b7a3" dependencies: @@ -3103,7 +3099,13 @@ tsutils@^1.4.0: version "1.9.1" resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-1.9.1.tgz#b9f9ab44e55af9681831d5f28d0aeeaf5c750cb0" -tsutils@^2.6.1, tsutils@^2.8.1, tsutils@^2.8.2: +tsutils@^2.11.1: + version "2.11.1" + resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-2.11.1.tgz#103dff3fa508aff5649c16dc4e6dd45dc41dbc62" + dependencies: + tslib "^1.7.1" + +tsutils@^2.6.1, tsutils@^2.8.1: version "2.8.2" resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-2.8.2.tgz#2c1486ba431260845b0ac6f902afd9d708a8ea6a" dependencies: @@ -3131,19 +3133,23 @@ typedarray@^0.0.6: version "0.0.6" resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" -typescript-parser@^1.3.3: - version "1.3.3" - resolved "https://registry.yarnpkg.com/typescript-parser/-/typescript-parser-1.3.3.tgz#7535082b89553b1e2a298292a953d4c6f6fd069f" +typescript-parser@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/typescript-parser/-/typescript-parser-2.0.1.tgz#ee6bc35b7e0cea47e0ab2f828e3ff6c16b6e3115" dependencies: - coveralls "^2.13.1" + coveralls "^2.13.3" lodash "^4.17.4" tslib "^1.7.1" typescript "2.4.2" -typescript@2.4.2, typescript@~2.4.2: +typescript@2.4.2: version "2.4.2" resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.4.2.tgz#f8395f85d459276067c988aa41837a8f82870844" +typescript@~2.5.3: + version "2.5.3" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.5.3.tgz#df3dcdc38f3beb800d4bc322646b04a3f6ca7f0d" + uglify-js@^2.6: version "2.8.29" resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-2.8.29.tgz#29c5733148057bb4e1f75df35b7a9cb72e6a59dd" @@ -3178,6 +3184,10 @@ unique-string@^1.0.0: dependencies: crypto-random-string "^1.0.0" +universalify@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.1.tgz#fa71badd4437af4c148841e3b3b165f9e9e590b7" + unzip-response@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/unzip-response/-/unzip-response-2.0.1.tgz#d2f0f737d16b0615e72a6935ed04214572d56f97" @@ -3227,6 +3237,12 @@ validate-npm-package-license@^3.0.1: spdx-correct "~1.0.0" spdx-expression-parse "~1.0.0" +validate-npm-package-name@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/validate-npm-package-name/-/validate-npm-package-name-3.0.0.tgz#5fa912d81eb7d0c74afc140de7317f0ca7df437e" + dependencies: + builtins "^1.0.3" + verror@1.10.0: version "1.10.0" resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400" From 47482040d711f89a506fe84dd6ce02a4cfd83824 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20B=C3=BChler?= Date: Wed, 4 Oct 2017 18:08:56 +0200 Subject: [PATCH 4/6] feat(document-outline): show getters and setters in outline (#314) Closes #257. --- .../DeclarationStructureTreeItem.ts | 19 +++++++++--- src/extension/utilities/utilityFunctions.ts | 31 +++++++++++-------- 2 files changed, 33 insertions(+), 17 deletions(-) diff --git a/src/extension/provider-items/document-structure/DeclarationStructureTreeItem.ts b/src/extension/provider-items/document-structure/DeclarationStructureTreeItem.ts index 0558c24..96b8cea 100644 --- a/src/extension/provider-items/document-structure/DeclarationStructureTreeItem.ts +++ b/src/extension/provider-items/document-structure/DeclarationStructureTreeItem.ts @@ -2,9 +2,11 @@ import { ClassDeclaration, Declaration, FunctionDeclaration, + GetterDeclaration, InterfaceDeclaration, MethodDeclaration, PropertyDeclaration, + SetterDeclaration, VariableDeclaration, } from 'typescript-parser'; import { stringTemplate } from 'typescript-parser/utilities/StringTemplate'; @@ -17,9 +19,9 @@ const fileTemplate = stringTemplate`./src/extension/assets/icons/declarations/${ /** * Function to calculate the displayed name of the declaration structure item. - * - * @param {Declaration} declaration - * @returns {string} + * + * @param {Declaration} declaration + * @returns {string} */ function getDeclarationLabel(declaration: Declaration): string { if ( @@ -41,12 +43,20 @@ function getDeclarationLabel(declaration: Declaration): string { return declaration.name + (declaration.typeParameters ? `<${declaration.typeParameters.join(', ')}>` : ''); } + if ( + declaration instanceof GetterDeclaration || + declaration instanceof SetterDeclaration + ) { + return `${declaration instanceof GetterDeclaration ? 'get' : 'set'}() ${declaration.name}` + + `${declaration.type ? `: ${declaration.type}` : ''}`; + } + return declaration.name; } /** * Structure item that represents a typescript declaration of any way. - * + * * @export * @class DeclarationStructureTreeItem * @extends {BaseStructureTreeItem} @@ -100,6 +110,7 @@ export class DeclarationStructureTreeItem extends BaseStructureTreeItem { this.declaration instanceof InterfaceDeclaration ) { return [ + ...this.declaration.accessors.map(p => new DeclarationStructureTreeItem(p, this.context)), ...this.declaration.properties.map(p => new DeclarationStructureTreeItem(p, this.context)), ...this.declaration.methods.map(m => new DeclarationStructureTreeItem(m, this.context)), ]; diff --git a/src/extension/utilities/utilityFunctions.ts b/src/extension/utilities/utilityFunctions.ts index 04a9fe7..f4e0456 100644 --- a/src/extension/utilities/utilityFunctions.ts +++ b/src/extension/utilities/utilityFunctions.ts @@ -5,12 +5,14 @@ import { DefaultDeclaration, EnumDeclaration, FunctionDeclaration, + GetterDeclaration, Import, InterfaceDeclaration, MethodDeclaration, ModuleDeclaration, ParameterDeclaration, PropertyDeclaration, + SetterDeclaration, SymbolSpecifier, TypeAliasDeclaration, VariableDeclaration, @@ -19,12 +21,12 @@ import { CompletionItemKind } from 'vscode'; /** * String-Sort function. - * + * * @export - * @param {string} strA - * @param {string} strB - * @param {('asc' | 'desc')} [order='asc'] - * @returns {number} + * @param {string} strA + * @param {string} strB + * @param {('asc' | 'desc')} [order='asc'] + * @returns {number} */ export function stringSort(strA: string, strB: string, order: 'asc' | 'desc' = 'asc'): number { let result: number = 0; @@ -41,12 +43,12 @@ export function stringSort(strA: string, strB: string, order: 'asc' | 'desc' = ' /** * Order imports by library name. - * + * * @export - * @param {Import} i1 - * @param {Import} i2 - * @param {('asc' | 'desc')} [order='asc'] - * @returns {number} + * @param {Import} i1 + * @param {Import} i2 + * @param {('asc' | 'desc')} [order='asc'] + * @returns {number} */ export function importSort(i1: Import, i2: Import, order: 'asc' | 'desc' = 'asc'): number { const strA = i1.libraryName.toLowerCase(); @@ -69,10 +71,10 @@ export function specifierSort(i1: SymbolSpecifier, i2: SymbolSpecifier): number /** * Returns the item kind for a given declaration. - * + * * @export - * @param {Declaration} declaration - * @returns {CompletionItemKind} + * @param {Declaration} declaration + * @returns {CompletionItemKind} */ export function getItemKind(declaration: Declaration): CompletionItemKind { switch (true) { @@ -103,6 +105,9 @@ export function getItemKind(declaration: Declaration): CompletionItemKind { return variable.isConst ? CompletionItemKind.Constant : CompletionItemKind.Variable; + case declaration instanceof GetterDeclaration: + case declaration instanceof SetterDeclaration: + return CompletionItemKind.Method; default: return CompletionItemKind.Reference; } From 17ae1916e4a38a35bd15bbf1eee70760fefa759d Mon Sep 17 00:00:00 2001 From: Daniel Prado Date: Thu, 5 Oct 2017 14:01:55 -0300 Subject: [PATCH 5/6] feat(organize): add configuration to disable removal of unsed imports (#315) Relates #311 --- README.md | 1 + package.json | 5 +++ src/common/config/ResolverConfig.ts | 8 ++++ src/extension/VscodeExtensionConfig.ts | 12 ++++++ src/extension/managers/ImportManager.ts | 38 ++++++++++--------- .../OrganizeImportsOnSaveExtension.test.ts | 30 +++++++++++++++ 6 files changed, 77 insertions(+), 17 deletions(-) diff --git a/README.md b/README.md index 4ccf861..b751c3b 100644 --- a/README.md +++ b/README.md @@ -90,6 +90,7 @@ The following settings do have the prefix `resolver`. So an example setting coul | multiLineWrapThreshold | The threshold, when imports are converted into multiline imports | | multiLineTrailingComma | When multiline imports are created, `true` inserts a trailing comma to the last line | | disableImportSorting | Disable sorting during organize imports action | +| disableImportRemovalOnOrganize | Disable removal unsed imports during organize imports action | | importGroups | The groups that are used for sorting the imports (description below) | | ignoreImportsForOrganize | Imports that are never removed during organize import (e.g. react) | | resolverMode | Which files should be considered to index for TypeScript Hero | diff --git a/package.json b/package.json index 3ba1d96..6ebfa4b 100644 --- a/package.json +++ b/package.json @@ -257,6 +257,11 @@ "default": false, "description": "Defines if sorting is disable during organize imports." }, + "typescriptHero.resolver.disableImportRemovalOnOrganize": { + "type": "boolean", + "default": false, + "description": "Defines, if removal unsed imports is obligatory during organize imports" + }, "typescriptHero.resolver.organizeOnSave": { "type": "boolean", "default": true, diff --git a/src/common/config/ResolverConfig.ts b/src/common/config/ResolverConfig.ts index 82ace44..85ff6d1 100644 --- a/src/common/config/ResolverConfig.ts +++ b/src/common/config/ResolverConfig.ts @@ -89,6 +89,14 @@ export interface ResolverConfig { */ disableImportSorting: boolean; + /** + * Disables removal of the unsed imports on organize. + * + * @type {boolean} + * @memberof ResolverConfig + */ + disableImportRemovalOnOrganize: boolean; + /** * List of import libraries ("from" part) which are ignored during the organize import function. * diff --git a/src/extension/VscodeExtensionConfig.ts b/src/extension/VscodeExtensionConfig.ts index 48cc457..23ac1dc 100644 --- a/src/extension/VscodeExtensionConfig.ts +++ b/src/extension/VscodeExtensionConfig.ts @@ -174,6 +174,18 @@ class VscodeResolverConfig implements ResolverConfig { return value !== undefined ? value : false; } + /** + * Defines, if removal unsed is obligatory during organize imports + * + * @readonly + * @type {boolean} + * @memberof ResolverConfig + */ + public get disableImportRemovalOnOrganize(): boolean { + const value = this.workspaceSection.get('resolver.disableImportRemovalOnOrganize'); + return value !== undefined ? value : false; + } + /** * Returns the tab size that is configured in vscode. * diff --git a/src/extension/managers/ImportManager.ts b/src/extension/managers/ImportManager.ts index 38a44c2..2bc5f0c 100644 --- a/src/extension/managers/ImportManager.ts +++ b/src/extension/managers/ImportManager.ts @@ -213,27 +213,31 @@ export class ImportManager implements ObjectManager { this.organize = true; let keep: Import[] = []; - for (const actImport of this.imports) { - if (ImportManager.config.resolver.ignoreImportsForOrganize.indexOf(actImport.libraryName) >= 0) { - keep.push(actImport); - continue; - } - if (actImport instanceof NamespaceImport || - actImport instanceof ExternalModuleImport) { - if (this._parsedDocument.nonLocalUsages.indexOf(actImport.alias) > -1) { + if (ImportManager.config.resolver.disableImportRemovalOnOrganize) { + keep = this.imports; + } else { + for (const actImport of this.imports) { + if (ImportManager.config.resolver.ignoreImportsForOrganize.indexOf(actImport.libraryName) >= 0) { keep.push(actImport); + continue; } - } else if (actImport instanceof NamedImport) { - actImport.specifiers = actImport.specifiers - .filter(o => this._parsedDocument.nonLocalUsages.indexOf(o.alias || o.specifier) > -1) - .sort(specifierSort); - const defaultSpec = actImport.defaultAlias; - if (actImport.specifiers.length || - (!!defaultSpec && this._parsedDocument.nonLocalUsages.indexOf(defaultSpec) >= 0)) { + if (actImport instanceof NamespaceImport || + actImport instanceof ExternalModuleImport) { + if (this._parsedDocument.nonLocalUsages.indexOf(actImport.alias) > -1) { + keep.push(actImport); + } + } else if (actImport instanceof NamedImport) { + actImport.specifiers = actImport.specifiers + .filter(o => this._parsedDocument.nonLocalUsages.indexOf(o.alias || o.specifier) > -1) + .sort(specifierSort); + const defaultSpec = actImport.defaultAlias; + if (actImport.specifiers.length || + (!!defaultSpec && this._parsedDocument.nonLocalUsages.indexOf(defaultSpec) >= 0)) { + keep.push(actImport); + } + } else if (actImport instanceof StringImport) { keep.push(actImport); } - } else if (actImport instanceof StringImport) { - keep.push(actImport); } } diff --git a/test/extension/extensions/OrganizeImportsOnSaveExtension.test.ts b/test/extension/extensions/OrganizeImportsOnSaveExtension.test.ts index 7d32629..71d138b 100644 --- a/test/extension/extensions/OrganizeImportsOnSaveExtension.test.ts +++ b/test/extension/extensions/OrganizeImportsOnSaveExtension.test.ts @@ -93,4 +93,34 @@ describe('OrganizeImportsOnSaveExtension', () => { ); }); + it('should not remove an unused import on save when disableImportRemovalOnOrganize is true', async () => { + const config = vscode.workspace.getConfiguration('typescriptHero'); + await config.update('resolver.disableImportRemovalOnOrganize', true); + + const ctrl = await ImportManager.create(document); + const declaration = index.declarationInfos.find(o => o.declaration.name === 'Class1'); + const declaration2 = index.declarationInfos.find(o => o.declaration.name === 'Class2'); + ctrl.addDeclarationImport(declaration!).addDeclarationImport(declaration2!); + await ctrl.commit(); + + document.lineAt(0).text.should.equals( + `import { Class1, Class2 } from '../../../server/indices/MyClass';`, + ); + + await vscode.window.activeTextEditor!.edit((builder) => { + builder.insert( + new vscode.Position(1, 0), + 'let a = new Class2()', + ); + }); + + await document.save(); + + document.lineAt(0).text.should.equals( + `import { Class1, Class2 } from '../../../server/indices/MyClass';`, + ); + + await config.update('resolver.disableImportRemovalOnOrganize', false); + }); + }); From 924a4c81b1bcc968c3bcef9e2f4d55b6c65b3ed4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20B=C3=BChler?= Date: Thu, 5 Oct 2017 08:31:42 +0200 Subject: [PATCH 6/6] feat(organizeOnSave): Set default option value to false --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 6ebfa4b..7df45c6 100644 --- a/package.json +++ b/package.json @@ -264,7 +264,7 @@ }, "typescriptHero.resolver.organizeOnSave": { "type": "boolean", - "default": true, + "default": false, "description": "Defines if the imports should be organized on save." }, "typescriptHero.resolver.ignoreImportsForOrganize": {