mirror of
https://github.com/zebrajr/node.git
synced 2026-01-15 12:15:26 +00:00
repl: support optional chaining during autocompletion
This makes sure the autocompletion is able to handle optional chaining notations. Signed-off-by: Ruben Bridgewater <ruben@bridgewater.de> PR-URL: https://github.com/nodejs/node/pull/33450 Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
This commit is contained in:
20
lib/repl.js
20
lib/repl.js
@@ -1066,7 +1066,7 @@ REPLServer.prototype.turnOffEditorMode = deprecate(
|
||||
const requireRE = /\brequire\s*\(\s*['"`](([\w@./-]+\/)?(?:[\w@./-]*))(?![^'"`])$/;
|
||||
const fsAutoCompleteRE = /fs(?:\.promises)?\.\s*[a-z][a-zA-Z]+\(\s*["'](.*)/;
|
||||
const simpleExpressionRE =
|
||||
/(?:[a-zA-Z_$](?:\w|\$)*\.)*[a-zA-Z_$](?:\w|\$)*\.?$/;
|
||||
/(?:[a-zA-Z_$](?:\w|\$)*\??\.)*[a-zA-Z_$](?:\w|\$)*\??\.?$/;
|
||||
|
||||
function isIdentifier(str) {
|
||||
if (str === '') {
|
||||
@@ -1138,7 +1138,7 @@ function complete(line, callback) {
|
||||
line = line.trimLeft();
|
||||
|
||||
// REPL commands (e.g. ".break").
|
||||
let filter;
|
||||
let filter = '';
|
||||
if (/^\s*\.(\w*)$/.test(line)) {
|
||||
completionGroups.push(ObjectKeys(this.commands));
|
||||
completeOn = line.match(/^\s*\.(\w*)$/)[1];
|
||||
@@ -1253,10 +1253,8 @@ function complete(line, callback) {
|
||||
let expr;
|
||||
completeOn = (match ? match[0] : '');
|
||||
if (line.length === 0) {
|
||||
filter = '';
|
||||
expr = '';
|
||||
} else if (line[line.length - 1] === '.') {
|
||||
filter = '';
|
||||
expr = match[0].slice(0, match[0].length - 1);
|
||||
} else {
|
||||
const bits = match[0].split('.');
|
||||
@@ -1285,6 +1283,12 @@ function complete(line, callback) {
|
||||
return;
|
||||
}
|
||||
|
||||
let chaining = '.';
|
||||
if (expr[expr.length - 1] === '?') {
|
||||
expr = expr.slice(0, -1);
|
||||
chaining = '?.';
|
||||
}
|
||||
|
||||
const evalExpr = `try { ${expr} } catch {}`;
|
||||
this.eval(evalExpr, this.context, 'repl', (e, obj) => {
|
||||
if (obj != null) {
|
||||
@@ -1316,12 +1320,12 @@ function complete(line, callback) {
|
||||
}
|
||||
|
||||
if (memberGroups.length) {
|
||||
for (let i = 0; i < memberGroups.length; i++) {
|
||||
completionGroups.push(
|
||||
memberGroups[i].map((member) => `${expr}.${member}`));
|
||||
expr += chaining;
|
||||
for (const group of memberGroups) {
|
||||
completionGroups.push(group.map((member) => `${expr}${member}`));
|
||||
}
|
||||
if (filter) {
|
||||
filter = `${expr}.${filter}`;
|
||||
filter = `${expr}${filter}`;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -68,6 +68,19 @@ testMe.complete('console.lo', common.mustCall(function(error, data) {
|
||||
assert.deepStrictEqual(data, [['console.log'], 'console.lo']);
|
||||
}));
|
||||
|
||||
testMe.complete('console?.lo', common.mustCall((error, data) => {
|
||||
assert.deepStrictEqual(data, [['console?.log'], 'console?.lo']);
|
||||
}));
|
||||
|
||||
testMe.complete('console?.zzz', common.mustCall((error, data) => {
|
||||
assert.deepStrictEqual(data, [[], 'console?.zzz']);
|
||||
}));
|
||||
|
||||
testMe.complete('console?.', common.mustCall((error, data) => {
|
||||
assert(data[0].includes('console?.log'));
|
||||
assert.strictEqual(data[1], 'console?.');
|
||||
}));
|
||||
|
||||
// Tab Complete will return globally scoped variables
|
||||
putIn.run(['};']);
|
||||
testMe.complete('inner.o', common.mustCall(function(error, data) {
|
||||
|
||||
Reference in New Issue
Block a user