Skip to content

Commit

Permalink
Merge pull request obsidian-tasks-group#3075 from obsidian-tasks-grou…
Browse files Browse the repository at this point in the history
…p/fix-filter-by-function-error-messages

fix: Make 'filter by function' show statement in error messages
  • Loading branch information
claremacrae authored Sep 11, 2024
2 parents d1d2655 + 9436277 commit 9572d0e
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -43,3 +43,34 @@ filename includes Custom Filters - Demo
# Infer tag from heading
filter by function task.heading.includes('#context/home') || task.tags.find( (tag) => tag === '#context/home' ) && true || false
```

## Demonstrate Error Handling

### Parsing Errors

This section demonstrate how Tasks handles errors when reading `filter by function` instructions.

#### SyntaxError

```tasks
filter by function \
task.due.formatAsDate(
```

### Evaluation Errors

This section demonstrate how Tasks handles when evaluating `filter by function` instructions during searches.

#### ReferenceError

```tasks
filter by function \
hello
```

#### Non-existent task field

```tasks
filter by function \
task.nonExistentField
```
21 changes: 18 additions & 3 deletions src/Query/Query.ts
Original file line number Diff line number Diff line change
Expand Up @@ -246,11 +246,15 @@ ${source}`;
}

private setError(message: string, statement: Statement) {
this._error = Query.generateErrorMessage(statement, message);
}

private static generateErrorMessage(statement: Statement, message: string) {
if (statement.allLinesIdentical()) {
this._error = `${message}
return `${message}
Problem line: "${statement.rawInstruction}"`;
} else {
this._error = `${message}
return `${message}
Problem statement:
${statement.explainStatement(' ')}
`;
Expand All @@ -265,10 +269,16 @@ ${statement.explainStatement(' ')}
this.debug(`Executing query: ${this.formatQueryForLogging()}`);

const searchInfo = new SearchInfo(this.tasksFile, tasks);

// Custom filter (filter by function) does not report the instruction line in any exceptions,
// for performance reasons. So we keep track of it here.
let possiblyBrokenStatement: Statement | undefined = undefined;
try {
this.filters.forEach((filter) => {
possiblyBrokenStatement = filter.statement;
tasks = tasks.filter((task) => filter.filterFunction(task, searchInfo));
});
possiblyBrokenStatement = undefined;

const { debugSettings } = getSettings();
const tasksSorted = debugSettings.ignoreSortInstructions ? tasks : Sort.by(this.sorting, tasks, searchInfo);
Expand All @@ -283,7 +293,12 @@ ${statement.explainStatement(' ')}
return new QueryResult(taskGroups, tasksSorted.length);
} catch (e) {
const description = 'Search failed';
return QueryResult.fromError(errorMessageForException(description, e));
let message = errorMessageForException(description, e);

if (possiblyBrokenStatement) {
message = Query.generateErrorMessage(possiblyBrokenStatement, message);
}
return QueryResult.fromError(message);
}
}

Expand Down
23 changes: 20 additions & 3 deletions tests/Query/Query.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1542,7 +1542,8 @@ describe('Query', () => {
describe('error handling', () => {
it('should catch an exception that occurs during searching', () => {
// Arrange
const source = 'filter by function wibble';
const source = `filter by function \\
wibble`;
const query = new Query(source);
const queryUpper = new Query(source.toUpperCase());
const task = TaskBuilder.createFullyPopulatedTask();
Expand All @@ -1553,10 +1554,26 @@ describe('Query', () => {

// Assert
expect(queryResult.searchErrorMessage).toEqual(
'Error: Search failed.\nThe error message was:\n "ReferenceError: wibble is not defined"',
`Error: Search failed.
The error message was:
"ReferenceError: wibble is not defined"
Problem statement:
filter by function \\
wibble
=>
filter by function wibble
`,
);
expect(queryResultUpper.searchErrorMessage).toEqual(
'Error: Search failed.\nThe error message was:\n "ReferenceError: WIBBLE is not defined"',
`Error: Search failed.
The error message was:
"ReferenceError: WIBBLE is not defined"
Problem statement:
FILTER BY FUNCTION \\
WIBBLE
=>
FILTER BY FUNCTION WIBBLE
`,
);
});
});
Expand Down

0 comments on commit 9572d0e

Please sign in to comment.