mirror of
https://github.com/zebrajr/node.git
synced 2025-12-07 12:20:50 +01:00
repl: fix tab completion not working with computer string properties
PR-URL: https://github.com/nodejs/node/pull/58709 Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com> Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de>
This commit is contained in:
parent
ea5d37ecbe
commit
07220230d9
|
|
@ -1226,7 +1226,7 @@ const importRE = /\bimport\s*\(\s*['"`](([\w@./:-]+\/)?(?:[\w@./:-]*))(?![^'"`])
|
||||||
const requireRE = /\brequire\s*\(\s*['"`](([\w@./:-]+\/)?(?:[\w@./:-]*))(?![^'"`])$/;
|
const requireRE = /\brequire\s*\(\s*['"`](([\w@./:-]+\/)?(?:[\w@./:-]*))(?![^'"`])$/;
|
||||||
const fsAutoCompleteRE = /fs(?:\.promises)?\.\s*[a-z][a-zA-Z]+\(\s*["'](.*)/;
|
const fsAutoCompleteRE = /fs(?:\.promises)?\.\s*[a-z][a-zA-Z]+\(\s*["'](.*)/;
|
||||||
const simpleExpressionRE =
|
const simpleExpressionRE =
|
||||||
/(?:[\w$'"`[{(](?:\w|\$|['"`\]})])*\??\.)*[a-zA-Z_$](?:\w|\$)*\??\.?$/;
|
/(?:[\w$'"`[{(](?:(\w| |\t)*?['"`]|\$|['"`\]})])*\??(?:\.|])?)*?(?:[a-zA-Z_$])?(?:\w|\$)*\??\.?$/;
|
||||||
const versionedFileNamesRe = /-\d+\.\d+/;
|
const versionedFileNamesRe = /-\d+\.\d+/;
|
||||||
|
|
||||||
function isIdentifier(str) {
|
function isIdentifier(str) {
|
||||||
|
|
|
||||||
130
test/parallel/test-repl-tab-complete-computed-props.js
Normal file
130
test/parallel/test-repl-tab-complete-computed-props.js
Normal file
|
|
@ -0,0 +1,130 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
const common = require('../common');
|
||||||
|
const ArrayStream = require('../common/arraystream');
|
||||||
|
const { describe, it, before, after } = require('node:test');
|
||||||
|
const assert = require('assert');
|
||||||
|
|
||||||
|
const repl = require('repl');
|
||||||
|
|
||||||
|
function prepareREPL() {
|
||||||
|
const input = new ArrayStream();
|
||||||
|
const replServer = repl.start({
|
||||||
|
prompt: '',
|
||||||
|
input,
|
||||||
|
output: process.stdout,
|
||||||
|
allowBlockingCompletions: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
// Some errors are passed to the domain, but do not callback
|
||||||
|
replServer._domain.on('error', assert.ifError);
|
||||||
|
|
||||||
|
return { replServer, input };
|
||||||
|
}
|
||||||
|
|
||||||
|
function testCompletion(replServer, { input, expectedCompletions }) {
|
||||||
|
replServer.complete(
|
||||||
|
input,
|
||||||
|
common.mustCall((_error, data) => {
|
||||||
|
assert.deepStrictEqual(data, [expectedCompletions, input]);
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
describe('REPL tab object completion on computed properties', () => {
|
||||||
|
describe('simple string cases', () => {
|
||||||
|
let replServer;
|
||||||
|
|
||||||
|
before(() => {
|
||||||
|
const { replServer: server, input } = prepareREPL();
|
||||||
|
replServer = server;
|
||||||
|
|
||||||
|
input.run([
|
||||||
|
`
|
||||||
|
const obj = {
|
||||||
|
one: 1,
|
||||||
|
innerObj: { two: 2 },
|
||||||
|
'inner object': { three: 3 },
|
||||||
|
};
|
||||||
|
|
||||||
|
const oneStr = 'one';
|
||||||
|
`,
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
after(() => {
|
||||||
|
replServer.close();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('works with double quoted strings', () => testCompletion(replServer, {
|
||||||
|
input: 'obj["one"].toFi',
|
||||||
|
expectedCompletions: ['obj["one"].toFixed'],
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('works with single quoted strings', () => testCompletion(replServer, {
|
||||||
|
input: "obj['one'].toFi",
|
||||||
|
expectedCompletions: ["obj['one'].toFixed"],
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('works with template strings', () => testCompletion(replServer, {
|
||||||
|
input: 'obj[`one`].toFi',
|
||||||
|
expectedCompletions: ['obj[`one`].toFixed'],
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('works with nested objects', () => {
|
||||||
|
testCompletion(replServer, {
|
||||||
|
input: 'obj["innerObj"].tw',
|
||||||
|
expectedCompletions: ['obj["innerObj"].two'],
|
||||||
|
});
|
||||||
|
testCompletion(replServer, {
|
||||||
|
input: 'obj["innerObj"].two.tofi',
|
||||||
|
expectedCompletions: ['obj["innerObj"].two.toFixed'],
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('works with nested objects combining different type of strings', () => testCompletion(replServer, {
|
||||||
|
input: 'obj["innerObj"][`two`].tofi',
|
||||||
|
expectedCompletions: ['obj["innerObj"][`two`].toFixed'],
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('works with strings with spaces', () => testCompletion(replServer, {
|
||||||
|
input: 'obj["inner object"].th',
|
||||||
|
expectedCompletions: ['obj["inner object"].three'],
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('variables as indexes', () => {
|
||||||
|
let replServer;
|
||||||
|
|
||||||
|
before(() => {
|
||||||
|
const { replServer: server, input } = prepareREPL();
|
||||||
|
replServer = server;
|
||||||
|
|
||||||
|
input.run([
|
||||||
|
`
|
||||||
|
const oneStr = 'One';
|
||||||
|
const helloWorldStr = 'Hello' + ' ' + 'World';
|
||||||
|
|
||||||
|
const obj = {
|
||||||
|
[oneStr]: 1,
|
||||||
|
['Hello World']: 'hello world!',
|
||||||
|
};
|
||||||
|
`,
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
after(() => {
|
||||||
|
replServer.close();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('works with a simple variable', () => testCompletion(replServer, {
|
||||||
|
input: 'obj[oneStr].toFi',
|
||||||
|
expectedCompletions: ['obj[oneStr].toFixed'],
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('works with a computed variable', () => testCompletion(replServer, {
|
||||||
|
input: 'obj[helloWorldStr].tolocaleup',
|
||||||
|
expectedCompletions: ['obj[helloWorldStr].toLocaleUpperCase'],
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
});
|
||||||
Loading…
Reference in New Issue
Block a user