fix handling of parenthesis without explicit AND operator, closes #3096

This commit is contained in:
zadam 2022-08-28 14:40:24 +02:00
parent 700e9fd912
commit 86d3a695ac
3 changed files with 43 additions and 10 deletions

4
package-lock.json generated
View File

@ -1,12 +1,12 @@
{
"name": "trilium",
"version": "0.54.2",
"version": "0.54.3",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "trilium",
"version": "0.54.2",
"version": "0.54.3",
"hasInstallScript": true,
"license": "AGPL-3.0-only",
"dependencies": {

View File

@ -211,6 +211,35 @@ describe("Parser", () => {
expect(secondSubSub.constructor.name).toEqual("LabelComparisonExp");
expect(secondSubSub.attributeName).toEqual("third");
});
it("label sub-expression without explicit operator", () => {
const rootExp = parse({
fulltextTokens: [],
expressionTokens: tokens(["#first", ["#second", "or", "#third"], "#fourth"]),
searchContext: new SearchContext()
});
expect(rootExp.constructor.name).toEqual("AndExp");
assertIsArchived(rootExp.subExpressions[0]);
expect(rootExp.subExpressions[1].constructor.name).toEqual("AndExp");
const [firstSub, secondSub, thirdSub] = rootExp.subExpressions[1].subExpressions;
expect(firstSub.constructor.name).toEqual("AttributeExistsExp");
expect(firstSub.attributeName).toEqual("first");
expect(secondSub.constructor.name).toEqual("OrExp");
const [firstSubSub, secondSubSub] = secondSub.subExpressions;
expect(firstSubSub.constructor.name).toEqual("AttributeExistsExp");
expect(firstSubSub.attributeName).toEqual("second");
expect(secondSubSub.constructor.name).toEqual("AttributeExistsExp");
expect(secondSubSub.attributeName).toEqual("third");
expect(thirdSub.constructor.name).toEqual("AttributeExistsExp");
expect(thirdSub.attributeName).toEqual("fourth");
});
});
describe("Invalid expressions", () => {

View File

@ -39,8 +39,12 @@ function getFulltext(tokens, searchContext) {
}
}
function isOperator(str) {
return str.match(/^[!=<>*%]+$/);
function isOperator(token) {
if (Array.isArray(token)) {
return false;
}
return token.token.match(/^[!=<>*%]+$/);
}
function getExpression(tokens, searchContext, level = 0) {
@ -129,16 +133,16 @@ function getExpression(tokens, searchContext, level = 0) {
i += 1;
const operator = tokens[i].token;
const operator = tokens[i];
if (!isOperator(operator)) {
searchContext.addError(`After content expected operator, but got "${tokens[i].token}" in ${context(i)}`);
searchContext.addError(`After content expected operator, but got "${operator.token}" in ${context(i)}`);
return;
}
i++;
return new NoteContentFulltextExp(operator, {tokens: [tokens[i].token], raw });
return new NoteContentFulltextExp(operator.token, {tokens: [tokens[i].token], raw });
}
if (tokens[i].token === 'parents') {
@ -228,7 +232,7 @@ function getExpression(tokens, searchContext, level = 0) {
function parseLabel(labelName) {
searchContext.highlightedTokens.push(labelName);
if (i < tokens.length - 2 && isOperator(tokens[i + 1].token)) {
if (i < tokens.length - 2 && isOperator(tokens[i + 1])) {
let operator = tokens[i + 1].token;
i += 2;
@ -265,7 +269,7 @@ function getExpression(tokens, searchContext, level = 0) {
return new RelationWhereExp(relationName, parseNoteProperty());
}
else if (i < tokens.length - 2 && isOperator(tokens[i + 1].token)) {
else if (i < tokens.length - 2 && isOperator(tokens[i + 1])) {
searchContext.addError(`Relation can be compared only with property, e.g. ~relation.title=hello in ${context(i)}`);
return null;
@ -384,7 +388,7 @@ function getExpression(tokens, searchContext, level = 0) {
searchContext.addError('Mixed usage of AND/OR - always use parenthesis to group AND/OR expressions.');
}
}
else if (isOperator(token)) {
else if (isOperator({token: token})) {
searchContext.addError(`Misplaced or incomplete expression "${token}"`);
}
else {