From 370bfda1546b06c10a15262e6d733f8fe6bf55d4 Mon Sep 17 00:00:00 2001 From: Mestery Date: Thu, 25 Nov 2021 01:01:30 +0100 Subject: [PATCH] repl: fix and extend require/import tab complete PR-URL: https://github.com/nodejs/node/pull/40216 Reviewed-By: Ruben Bridgewater Reviewed-By: James M Snell --- lib/repl.js | 214 +++++++++--------- .../parallel/test-repl-tab-complete-import.js | 4 +- test/parallel/test-repl-tab-complete.js | 4 +- 3 files changed, 108 insertions(+), 114 deletions(-) diff --git a/lib/repl.js b/lib/repl.js index c85ccbde5a44ac..43af9c7c0e09a9 100644 --- a/lib/repl.js +++ b/lib/repl.js @@ -125,7 +125,7 @@ const { Console } = require('console'); const CJSModule = require('internal/modules/cjs/loader').Module; let _builtinLibs = ArrayPrototypeFilter( CJSModule.builtinModules, - (e) => !StringPrototypeStartsWith(e, '_') && !StringPrototypeIncludes(e, '/') + (e) => !StringPrototypeStartsWith(e, '_'), ); const nodeSchemeBuiltinLibs = ArrayPrototypeMap( _builtinLibs, (lib) => `node:${lib}`); @@ -1287,135 +1287,133 @@ function complete(line, callback) { if (completeOn.length) { filter = completeOn; } - } else if (RegExpPrototypeTest(requireRE, line) && - this.allowBlockingCompletions) { + } else if (RegExpPrototypeTest(requireRE, line)) { // require('...') - const extensions = ObjectKeys(this.context.require.extensions); - const indexes = ArrayPrototypeMap(extensions, - (extension) => `index${extension}`); - ArrayPrototypePush(indexes, 'package.json', 'index'); - const match = StringPrototypeMatch(line, requireRE); completeOn = match[1]; - const subdir = match[2] || ''; filter = completeOn; - group = []; - let paths = []; - - if (completeOn === '.') { - group = ['./', '../']; - } else if (completeOn === '..') { - group = ['../']; - } else if (RegExpPrototypeTest(/^\.\.?\//, completeOn)) { - paths = [process.cwd()]; - } else { - paths = ArrayPrototypeConcat(module.paths, CJSModule.globalPaths); - } + if (this.allowBlockingCompletions) { + const subdir = match[2] || ''; + const extensions = ObjectKeys(this.context.require.extensions); + const indexes = ArrayPrototypeMap(extensions, + (extension) => `index${extension}`); + ArrayPrototypePush(indexes, 'package.json', 'index'); + + group = []; + let paths = []; + + if (completeOn === '.') { + group = ['./', '../']; + } else if (completeOn === '..') { + group = ['../']; + } else if (RegExpPrototypeTest(/^\.\.?\//, completeOn)) { + paths = [process.cwd()]; + } else { + paths = ArrayPrototypeConcat(module.paths, CJSModule.globalPaths); + } - ArrayPrototypeForEach(paths, (dir) => { - dir = path.resolve(dir, subdir); - const dirents = gracefulReaddir(dir, { withFileTypes: true }) || []; - ArrayPrototypeForEach(dirents, (dirent) => { - if (RegExpPrototypeTest(versionedFileNamesRe, dirent.name) || - dirent.name === '.npm') { - // Exclude versioned names that 'npm' installs. - return; - } - const extension = path.extname(dirent.name); - const base = StringPrototypeSlice(dirent.name, 0, -extension.length); - if (!dirent.isDirectory()) { - if (StringPrototypeIncludes(extensions, extension) && - (!subdir || base !== 'index')) { - ArrayPrototypePush(group, `${subdir}${base}`); + ArrayPrototypeForEach(paths, (dir) => { + dir = path.resolve(dir, subdir); + const dirents = gracefulReaddir(dir, { withFileTypes: true }) || []; + ArrayPrototypeForEach(dirents, (dirent) => { + if (RegExpPrototypeTest(versionedFileNamesRe, dirent.name) || + dirent.name === '.npm') { + // Exclude versioned names that 'npm' installs. + return; } - return; - } - ArrayPrototypePush(group, `${subdir}${dirent.name}/`); - const absolute = path.resolve(dir, dirent.name); - if (ArrayPrototypeSome( - gracefulReaddir(absolute) || [], - (subfile) => ArrayPrototypeIncludes(indexes, subfile) - )) { - ArrayPrototypePush(group, `${subdir}${dirent.name}`); - } + const extension = path.extname(dirent.name); + const base = StringPrototypeSlice(dirent.name, 0, -extension.length); + if (!dirent.isDirectory()) { + if (StringPrototypeIncludes(extensions, extension) && + (!subdir || base !== 'index')) { + ArrayPrototypePush(group, `${subdir}${base}`); + } + return; + } + ArrayPrototypePush(group, `${subdir}${dirent.name}/`); + const absolute = path.resolve(dir, dirent.name); + if (ArrayPrototypeSome( + gracefulReaddir(absolute) || [], + (subfile) => ArrayPrototypeIncludes(indexes, subfile) + )) { + ArrayPrototypePush(group, `${subdir}${dirent.name}`); + } + }); }); - }); - if (group.length) { - ArrayPrototypePush(completionGroups, group); + if (group.length) { + ArrayPrototypePush(completionGroups, group); + } } - if (!subdir) { - ArrayPrototypePush(completionGroups, _builtinLibs, nodeSchemeBuiltinLibs); - } - } else if (RegExpPrototypeTest(importRE, line) && - this.allowBlockingCompletions) { + ArrayPrototypePush(completionGroups, _builtinLibs, nodeSchemeBuiltinLibs); + } else if (RegExpPrototypeTest(importRE, line)) { // import('...') - // File extensions that can be imported: - const extensions = ObjectKeys( - getOptionValue('--experimental-specifier-resolution') === 'node' ? - legacyExtensionFormatMap : - extensionFormatMap); - - // Only used when loading bare module specifiers from `node_modules`: - const indexes = ArrayPrototypeMap(extensions, (ext) => `index${ext}`); - ArrayPrototypePush(indexes, 'package.json'); - const match = StringPrototypeMatch(line, importRE); completeOn = match[1]; - const subdir = match[2] || ''; filter = completeOn; - group = []; - let paths = []; - if (completeOn === '.') { - group = ['./', '../']; - } else if (completeOn === '..') { - group = ['../']; - } else if (RegExpPrototypeTest(/^\.\.?\//, completeOn)) { - paths = [process.cwd()]; - } else { - paths = ArrayPrototypeSlice(module.paths); - } + if (this.allowBlockingCompletions) { + const subdir = match[2] || ''; + // File extensions that can be imported: + const extensions = ObjectKeys( + getOptionValue('--experimental-specifier-resolution') === 'node' ? + legacyExtensionFormatMap : + extensionFormatMap); + + // Only used when loading bare module specifiers from `node_modules`: + const indexes = ArrayPrototypeMap(extensions, (ext) => `index${ext}`); + ArrayPrototypePush(indexes, 'package.json'); + + group = []; + let paths = []; + if (completeOn === '.') { + group = ['./', '../']; + } else if (completeOn === '..') { + group = ['../']; + } else if (RegExpPrototypeTest(/^\.\.?\//, completeOn)) { + paths = [process.cwd()]; + } else { + paths = ArrayPrototypeSlice(module.paths); + } - ArrayPrototypeForEach(paths, (dir) => { - dir = path.resolve(dir, subdir); - const isInNodeModules = path.basename(dir) === 'node_modules'; - const dirents = gracefulReaddir(dir, { withFileTypes: true }) || []; - ArrayPrototypeForEach(dirents, (dirent) => { - const { name } = dirent; - if (RegExpPrototypeTest(versionedFileNamesRe, name) || - name === '.npm') { - // Exclude versioned names that 'npm' installs. - return; - } + ArrayPrototypeForEach(paths, (dir) => { + dir = path.resolve(dir, subdir); + const isInNodeModules = path.basename(dir) === 'node_modules'; + const dirents = gracefulReaddir(dir, { withFileTypes: true }) || []; + ArrayPrototypeForEach(dirents, (dirent) => { + const { name } = dirent; + if (RegExpPrototypeTest(versionedFileNamesRe, name) || + name === '.npm') { + // Exclude versioned names that 'npm' installs. + return; + } - if (!dirent.isDirectory()) { - const extension = path.extname(name); - if (StringPrototypeIncludes(extensions, extension)) { - ArrayPrototypePush(group, `${subdir}${name}`); + if (!dirent.isDirectory()) { + const extension = path.extname(name); + if (StringPrototypeIncludes(extensions, extension)) { + ArrayPrototypePush(group, `${subdir}${name}`); + } + return; } - return; - } - ArrayPrototypePush(group, `${subdir}${name}/`); - if (!subdir && isInNodeModules) { - const absolute = path.resolve(dir, name); - const subfiles = gracefulReaddir(absolute) || []; - if (ArrayPrototypeSome(subfiles, (subfile) => { - return ArrayPrototypeIncludes(indexes, subfile); - })) { - ArrayPrototypePush(group, `${subdir}${name}`); + ArrayPrototypePush(group, `${subdir}${name}/`); + if (!subdir && isInNodeModules) { + const absolute = path.resolve(dir, name); + const subfiles = gracefulReaddir(absolute) || []; + if (ArrayPrototypeSome(subfiles, (subfile) => { + return ArrayPrototypeIncludes(indexes, subfile); + })) { + ArrayPrototypePush(group, `${subdir}${name}`); + } } - } + }); }); - }); - if (group.length) { - ArrayPrototypePush(completionGroups, group); + if (group.length) { + ArrayPrototypePush(completionGroups, group); + } } - if (!subdir) { - ArrayPrototypePush(completionGroups, _builtinLibs, nodeSchemeBuiltinLibs); - } + ArrayPrototypePush(completionGroups, _builtinLibs, nodeSchemeBuiltinLibs); } else if (RegExpPrototypeTest(fsAutoCompleteRE, line) && this.allowBlockingCompletions) { ({ 0: completionGroups, 1: completeOn } = completeFSFunctions(line)); diff --git a/test/parallel/test-repl-tab-complete-import.js b/test/parallel/test-repl-tab-complete-import.js index 414b5cc4eac103..1968caa5accf54 100644 --- a/test/parallel/test-repl-tab-complete-import.js +++ b/test/parallel/test-repl-tab-complete-import.js @@ -5,9 +5,7 @@ const ArrayStream = require('../common/arraystream'); const fixtures = require('../common/fixtures'); const assert = require('assert'); const { builtinModules } = require('module'); -const publicModules = builtinModules.filter( - (lib) => !lib.startsWith('_') && !lib.includes('/'), -); +const publicModules = builtinModules.filter((lib) => !lib.startsWith('_')); if (!common.isMainThread) common.skip('process.chdir is not available in Workers'); diff --git a/test/parallel/test-repl-tab-complete.js b/test/parallel/test-repl-tab-complete.js index 9597c2a3480f33..aa5c7958a58b2e 100644 --- a/test/parallel/test-repl-tab-complete.js +++ b/test/parallel/test-repl-tab-complete.js @@ -31,9 +31,7 @@ const assert = require('assert'); const path = require('path'); const fixtures = require('../common/fixtures'); const { builtinModules } = require('module'); -const publicModules = builtinModules.filter( - (lib) => !lib.startsWith('_') && !lib.includes('/'), -); +const publicModules = builtinModules.filter((lib) => !lib.startsWith('_')); const hasInspector = process.features.inspector;