| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent 95842db commit 6257cf2
4 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1046,7 +1046,7 @@ REPLServer.prototype.turnOffEditorMode = deprecate( | |||
| 1046 | 1046 | 'REPLServer.turnOffEditorMode() is deprecated', | |
| 1047 | 1047 | 'DEP0078'); | |
| 1048 | 1048 | ||
| 1049 | - const requireRE = /\brequire\s*\(['"](([\w@./-]+\/)?(?:[\w@./-]*))/; | ||
| 1049 | + const requireRE = /\brequire\s*\(\s*['"`](([\w@./-]+\/)?(?:[\w@./-]*))(?![^'"`])$/; | ||
| 1050 | 1050 | const fsAutoCompleteRE = /fs(?:\.promises)?\.\s*[a-z][a-zA-Z]+\(\s*["'](.*)/; | |
| 1051 | 1051 | const simpleExpressionRE = | |
| 1052 | 1052 | /(?:[a-zA-Z_$](?:\w|\$)*\.)*[a-zA-Z_$](?:\w|\$)*\.?$/; | |
@@ -1094,8 +1094,13 @@ REPLServer.prototype.complete = function() { | |||
| 1094 | 1094 | this.completer.apply(this, arguments); | |
| 1095 | 1095 | }; | |
| 1096 | 1096 | ||
| 1097 | - // TODO: Native module names should be auto-resolved. | ||
| 1098 | - // That improves the auto completion. | ||
| 1097 | + function gracefulOperation(fn, args, alternative) { | ||
| 1098 | + try { | ||
| 1099 | + return fn(...args); | ||
| 1100 | + } catch { | ||
| 1101 | + return alternative; | ||
| 1102 | + } | ||
| 1103 | + } | ||
| 1099 | 1104 | ||
| 1100 | 1105 | // Provide a list of completions for the given leading text. This is | |
| 1101 | 1106 | // given to the readline interface for handling tab completion. | |
@@ -1117,26 +1122,25 @@ function complete(line, callback) { | |||
| 1117 | 1122 | ||
| 1118 | 1123 | // REPL commands (e.g. ".break"). | |
| 1119 | 1124 | let filter; | |
| 1120 | - let match = line.match(/^\s*\.(\w*)$/); | ||
| 1121 | - if (match) { | ||
| 1125 | + if (/^\s*\.(\w*)$/.test(line)) { | ||
| 1122 | 1126 | completionGroups.push(ObjectKeys(this.commands)); | |
| 1123 | - completeOn = match[1]; | ||
| 1124 | - if (match[1].length) { | ||
| 1125 | - filter = match[1]; | ||
| 1127 | + completeOn = line.match(/^\s*\.(\w*)$/)[1]; | ||
| 1128 | + if (completeOn.length) { | ||
| 1129 | + filter = completeOn; | ||
| 1126 | 1130 | } | |
| 1127 | 1131 | ||
| 1128 | 1132 | completionGroupsLoaded(); | |
| 1129 | - } else if (match = line.match(requireRE)) { | ||
| 1133 | + } else if (requireRE.test(line)) { | ||
| 1130 | 1134 | // require('...<Tab>') | |
| 1131 | - const exts = ObjectKeys(this.context.require.extensions); | ||
| 1132 | - const indexRe = new RegExp('^index(?:' + exts.map(regexpEscape).join('|') + | ||
| 1133 | - ')$'); | ||
| 1135 | + const extensions = ObjectKeys(this.context.require.extensions); | ||
| 1136 | + const indexes = extensions.map((extension) => `index${extension}`); | ||
| 1137 | + indexes.push('package.json', 'index'); | ||
| 1134 | 1138 | const versionedFileNamesRe = /-\d+\.\d+/; | |
| 1135 | 1139 | ||
| 1140 | + const match = line.match(requireRE); | ||
| 1136 | 1141 | completeOn = match[1]; | |
| 1137 | 1142 | const subdir = match[2] || ''; | |
| 1138 | - filter = match[1]; | ||
| 1139 | - let dir, files, subfiles, isDirectory; | ||
| 1143 | + filter = completeOn; | ||
| 1140 | 1144 | group = []; | |
| 1141 | 1145 | let paths = []; | |
| 1142 | 1146 | ||
@@ -1150,41 +1154,34 @@ function complete(line, callback) { | |||
| 1150 | 1154 | paths = module.paths.concat(CJSModule.globalPaths); | |
| 1151 | 1155 | } | |
| 1152 | 1156 | ||
| 1153 | - for (let i = 0; i < paths.length; i++) { | ||
| 1154 | - dir = path.resolve(paths[i], subdir); | ||
| 1155 | - try { | ||
| 1156 | - files = fs.readdirSync(dir); | ||
| 1157 | - } catch { | ||
| 1158 | - continue; | ||
| 1159 | - } | ||
| 1160 | - for (let f = 0; f < files.length; f++) { | ||
| 1161 | - const name = files[f]; | ||
| 1162 | - const ext = path.extname(name); | ||
| 1163 | - const base = name.slice(0, -ext.length); | ||
| 1164 | - if (versionedFileNamesRe.test(base) || name === '.npm') { | ||
| 1157 | + for (let dir of paths) { | ||
| 1158 | + dir = path.resolve(dir, subdir); | ||
| 1159 | + const dirents = gracefulOperation( | ||
| 1160 | + fs.readdirSync, | ||
| 1161 | + [dir, { withFileTypes: true }], | ||
| 1162 | + [] | ||
| 1163 | + ); | ||
| 1164 | + for (const dirent of dirents) { | ||
| 1165 | + if (versionedFileNamesRe.test(dirent.name) || dirent.name === '.npm') { | ||
| 1165 | 1166 | // Exclude versioned names that 'npm' installs. | |
| 1166 | 1167 | continue; | |
| 1167 | 1168 | } | |
| 1168 | - const abs = path.resolve(dir, name); | ||
| 1169 | - try { | ||
| 1170 | - isDirectory = fs.statSync(abs).isDirectory(); | ||
| 1171 | - } catch { | ||
| 1169 | + const extension = path.extname(dirent.name); | ||
| 1170 | + const base = dirent.name.slice(0, -extension.length); | ||
| 1171 | + if (!dirent.isDirectory()) { | ||
| 1172 | + if (extensions.includes(extension) && (!subdir || base !== 'index')) { | ||
| 1173 | + group.push(`${subdir}${base}`); | ||
| 1174 | + } | ||
| 1172 | 1175 | continue; | |
| 1173 | 1176 | } | |
| 1174 | - if (isDirectory) { | ||
| 1175 | - group.push(subdir + name + '/'); | ||
| 1176 | - try { | ||
| 1177 | - subfiles = fs.readdirSync(abs); | ||
| 1178 | - } catch { | ||
| 1179 | - continue; | ||
| 1177 | + group.push(`${subdir}${dirent.name}/`); | ||
| 1178 | + const absolute = path.resolve(dir, dirent.name); | ||
| 1179 | + const subfiles = gracefulOperation(fs.readdirSync, [absolute], []); | ||
| 1180 | + for (const subfile of subfiles) { | ||
| 1181 | + if (indexes.includes(subfile)) { | ||
| 1182 | + group.push(`${subdir}${dirent.name}`); | ||
| 1183 | + break; | ||
| 1180 | 1184 | } | |
| 1181 | - for (let s = 0; s < subfiles.length; s++) { | ||
| 1182 | - if (indexRe.test(subfiles[s])) { | ||
| 1183 | - group.push(subdir + name); | ||
| 1184 | - } | ||
| 1185 | - } | ||
| 1186 | - } else if (exts.includes(ext) && (!subdir || base !== 'index')) { | ||
| 1187 | - group.push(subdir + base); | ||
| 1188 | 1185 | } | |
| 1189 | 1186 | } | |
| 1190 | 1187 | } | |
@@ -1197,11 +1194,10 @@ function complete(line, callback) { | |||
| 1197 | 1194 | } | |
| 1198 | 1195 | ||
| 1199 | 1196 | completionGroupsLoaded(); | |
| 1200 | - } else if (match = line.match(fsAutoCompleteRE)) { | ||
| 1201 | - | ||
| 1202 | - let filePath = match[1]; | ||
| 1203 | - let fileList; | ||
| 1197 | + } else if (fsAutoCompleteRE.test(line)) { | ||
| 1204 | 1198 | filter = ''; | |
| 1199 | + let filePath = line.match(fsAutoCompleteRE)[1]; | ||
| 1200 | + let fileList; | ||
| 1205 | 1201 | ||
| 1206 | 1202 | try { | |
| 1207 | 1203 | fileList = fs.readdirSync(filePath, { withFileTypes: true }); | |
@@ -1232,7 +1228,7 @@ function complete(line, callback) { | |||
| 1232 | 1228 | // foo<|> # all scope vars with filter 'foo' | |
| 1233 | 1229 | // foo.<|> # completions for 'foo' with filter '' | |
| 1234 | 1230 | } else if (line.length === 0 || /\w|\.|\$/.test(line[line.length - 1])) { | |
| 1235 | - match = simpleExpressionRE.exec(line); | ||
| 1231 | + const match = simpleExpressionRE.exec(line); | ||
| 1236 | 1232 | if (line.length !== 0 && !match) { | |
| 1237 | 1233 | completionGroupsLoaded(); | |
| 1238 | 1234 | return; | |
@@ -1582,10 +1578,6 @@ function defineDefaultCommands(repl) { | |||
| 1582 | 1578 | } | |
| 1583 | 1579 | } | |
| 1584 | 1580 | ||
| 1585 | - function regexpEscape(s) { | ||
| 1586 | - return s.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&'); | ||
| 1587 | - } | ||
| 1588 | - | ||
| 1589 | 1581 | function Recoverable(err) { | |
| 1590 | 1582 | this.err = err; | |
| 1591 | 1583 | } | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -229,24 +229,46 @@ testMe.complete('require(\'', common.mustCall(function(error, data) { | |||
| 229 | 229 | }); | |
| 230 | 230 | })); | |
| 231 | 231 | ||
| 232 | - testMe.complete('require(\'n', common.mustCall(function(error, data) { | ||
| 232 | + testMe.complete("require\t( 'n", common.mustCall(function(error, data) { | ||
| 233 | 233 | assert.strictEqual(error, null); | |
| 234 | 234 | assert.strictEqual(data.length, 2); | |
| 235 | 235 | assert.strictEqual(data[1], 'n'); | |
| 236 | - assert(data[0].includes('net')); | ||
| 236 | + // There is only one Node.js module that starts with n: | ||
| 237 | + assert.strictEqual(data[0][0], 'net'); | ||
| 238 | + assert.strictEqual(data[0][1], ''); | ||
| 237 | 239 | // It's possible to pick up non-core modules too | |
| 238 | - data[0].forEach(function(completion) { | ||
| 239 | - if (completion) | ||
| 240 | - assert(/^n/.test(completion)); | ||
| 240 | + data[0].slice(2).forEach((completion) => { | ||
| 241 | + assert.match(completion, /^n/); | ||
| 241 | 242 | }); | |
| 242 | 243 | })); | |
| 243 | 244 | ||
| 244 | 245 | { | |
| 245 | 246 | const expected = ['@nodejsscope', '@nodejsscope/']; | |
| 247 | + // Require calls should handle all types of quotation marks. | ||
| 248 | + for (const quotationMark of ["'", '"', '`']) { | ||
| 249 | + putIn.run(['.clear']); | ||
| 250 | + testMe.complete('require(`@nodejs', common.mustCall((err, data) => { | ||
| 251 | + assert.strictEqual(err, null); | ||
| 252 | + assert.deepStrictEqual(data, [expected, '@nodejs']); | ||
| 253 | + })); | ||
| 254 | + | ||
| 255 | + putIn.run(['.clear']); | ||
| 256 | + // Completions should not be greedy in case the quotation ends. | ||
| 257 | + const input = `require(${quotationMark}@nodejsscope${quotationMark}`; | ||
| 258 | + testMe.complete(input, common.mustCall((err, data) => { | ||
| 259 | + assert.strictEqual(err, null); | ||
| 260 | + assert.deepStrictEqual(data, [[], undefined]); | ||
| 261 | + })); | ||
| 262 | + } | ||
| 263 | + } | ||
| 264 | + | ||
| 265 | + { | ||
| 246 | 266 | putIn.run(['.clear']); | |
| 247 | - testMe.complete('require(\'@nodejs', common.mustCall((err, data) => { | ||
| 267 | + // Completions should find modules and handle whitespace after the opening | ||
| 268 | + // bracket. | ||
| 269 | + testMe.complete('require \t("no_ind', common.mustCall((err, data) => { | ||
| 248 | 270 | assert.strictEqual(err, null); | |
| 249 | - assert.deepStrictEqual(data, [expected, '@nodejs']); | ||
| 271 | + assert.deepStrictEqual(data, [['no_index', 'no_index/'], 'no_ind']); | ||
| 250 | 272 | })); | |
| 251 | 273 | } | |
| 252 | 274 | ||
| Back | FazBrowse Home | New Git URL |
0 commit comments