Repository: obsidian-tasks-group/obsidian-tasks
Pull request #2292 (2023-09-25 08:22:26)

refactor: remove destructured types in Query.ts
# Description

Remove destructured types from `Query.constructor()` and other methods:

`new Query({ source }, path);` -> `new Query(source, path);`

## Motivation and Context

Cleaner and shorter code.

## How has this been tested?

Unit tests.

## Types of changes

Internal changes:

- [x] **Refactor** (prefix: `refactor` - non-breaking change which only improves the design or structure of existing code, and making no changes to its external behaviour)
- [x] **Tests** (prefix: `test` - additions and improvements to unit tests and the smoke tests)

## Checklist

- [x] My code follows the code style of this project and passes `yarn run lint`.
- [x] My change has adequate [Unit Test coverage](https://publish.obsidian.md/tasks-contributing/Testing/About+Testing).

## Terms

- [x] My contribution follow this project's [contributing guide](https://publish.obsidian.md/tasks-contributing)
- [x] I agree to follow this project's [Code of Conduct](https://github.com/obsidian-tasks-group/obsidian-tasks/blob/main/CODE_OF_CONDUCT.md)



Patch:
diff --git a/src/Config/GlobalQuery.ts b/src/Config/GlobalQuery.ts
index 9b6dc3f9..3958b912 100644
--- a/src/Config/GlobalQuery.ts
+++ b/src/Config/GlobalQuery.ts
@@ -49,7 +49,7 @@ export class GlobalQuery {
      * @param path
      */
     public query(path: string | undefined = undefined): Query {
-        return new Query({ source: this._source }, path);
+        return new Query(this._source, path);
     }
 
     /**
diff --git a/src/Query/Query.ts b/src/Query/Query.ts
index 8d2ac45f..2af1273a 100644
--- a/src/Query/Query.ts
+++ b/src/Query/Query.ts
@@ -37,7 +37,7 @@ export class Query implements IQuery {
 
     private readonly commentRegexp = /^#.*/;
 
-    constructor({ source }: { source: string }, path: string | undefined = undefined) {
+    constructor(source: string, path: string | undefined = undefined) {
         this.source = source;
         this.filePath = path;
 
@@ -64,14 +64,14 @@ export class Query implements IQuery {
                         this._ignoreGlobalQuery = true;
                         break;
                     case this.limitRegexp.test(line):
-                        this.parseLimit({ line });
+                        this.parseLimit(line);
                         break;
-                    case this.parseSortBy({ line }):
+                    case this.parseSortBy(line):
                         break;
-                    case this.parseGroupBy({ line }):
+                    case this.parseGroupBy(line):
                         break;
                     case this.hideOptionsRegexp.test(line):
-                        this.parseHideOptions({ line });
+                        this.parseHideOptions(line);
                         break;
                     case this.commentRegexp.test(line):
                         // Comment lines are ignored
@@ -138,7 +138,7 @@ ${source}`;
     public append(q2: Query): Query {
         if (this.source === '') return q2;
         if (q2.source === '') return this;
-        return new Query({ source: `${this.source}\n${q2.source}` }, this.filePath);
+        return new Query(`${this.source}\n${q2.source}`, this.filePath);
     }
 
     /**
@@ -258,7 +258,7 @@ Problem line: "${line}"`;
         }
     }
 
-    private parseHideOptions({ line }: { line: string }): void {
+    private parseHideOptions(line: string): void {
         const hideOptionsMatch = line.match(this.hideOptionsRegexp);
         if (hideOptionsMatch !== null) {
             const hide = hideOptionsMatch[1] === 'hide';
@@ -320,7 +320,7 @@ Problem line: "${line}"`;
         return false;
     }
 
-    private parseLimit({ line }: { line: string }): void {
+    private parseLimit(line: string): void {
         const limitMatch = line.match(this.limitRegexp);
         if (limitMatch === null) {
             this.setError('do not understand query limit', line);
@@ -337,7 +337,7 @@ Problem line: "${line}"`;
         }
     }
 
-    private parseSortBy({ line }: { line: string }): boolean {
+    private parseSortBy(line: string): boolean {
         const sortingMaybe = FilterParser.parseSorter(line);
         if (sortingMaybe) {
             this._sorting.push(sortingMaybe);
@@ -353,7 +353,7 @@ Problem line: "${line}"`;
      * @param line
      * @private
      */
-    private parseGroupBy({ line }: { line: string }): boolean {
+    private parseGroupBy(line: string): boolean {
         const groupingMaybe = FilterParser.parseGrouper(line);
         if (groupingMaybe) {
             this._grouping.push(groupingMaybe);
diff --git a/src/lib/QueryRendererHelper.ts b/src/lib/QueryRendererHelper.ts
index 3d0e1c81..1221f2d8 100644
--- a/src/lib/QueryRendererHelper.ts
+++ b/src/lib/QueryRendererHelper.ts
@@ -36,7 +36,7 @@ export function explainResults(
         result += `Only tasks containing the global filter '${globalFilter.get()}'.\n\n`;
     }
 
-    const tasksBlockQuery = new Query({ source }, path);
+    const tasksBlockQuery = new Query(source, path);
 
     if (!tasksBlockQuery.ignoreGlobalQuery) {
         if (globalQuery.hasInstructions()) {
@@ -60,7 +60,7 @@ export function explainResults(
  * @returns {Query} The query to execute
  */
 export function getQueryForQueryRenderer(source: string, globalQuery: GlobalQuery, path: string | undefined): Query {
-    const tasksBlockQuery = new Query({ source }, path);
+    const tasksBlockQuery = new Query(source, path);
 
     if (tasksBlockQuery.ignoreGlobalQuery) {
         return tasksBlockQuery;


Test patch:
diff --git a/tests/Config/DebugSettings.test.ts b/tests/Config/DebugSettings.test.ts
index fefabbc7..7b2a345a 100644
--- a/tests/Config/DebugSettings.test.ts
+++ b/tests/Config/DebugSettings.test.ts
@@ -17,12 +17,10 @@ describe('DebugSettings', () => {
 `;
         const tasks = createTasksFromMarkdown(tasksAsMarkdown, 'some_markdown_file', 'Some Heading');
 
-        const query = new Query({
-            source: `
+        const query = new Query(`
             sort by status
             explain
-        `,
-        }); // Would put Task 3 first
+        `); // Would put Task 3 first
 
         // Disable sort instructions
         updateSettings({ debugSettings: new DebugSettings(true) });
diff --git a/tests/Query.test.ts b/tests/Query.test.ts
index 2f1f3fcc..0bc64296 100644
--- a/tests/Query.test.ts
+++ b/tests/Query.test.ts
@@ -146,7 +146,7 @@ describe('Query parsing', () => {
     describe('should recognise every supported filter', () => {
         test.concurrent.each<string>(filters)('recognises %j', (filter) => {
             // Arrange
-            const query = new Query({ source: filter });
+            const query = new Query(filter);
 
             // Assert
             expect(query.error).toBeUndefined();
@@ -192,7 +192,7 @@ describe('Query parsing', () => {
             // For every sub-query from the filters list above, compose a boolean query that is always
             // true, in the format (expression) OR NOT (expression)
             const queryString = `(${filter}) OR NOT (${filter})`;
-            const query = new Query({ source: queryString });
+            const query = new Query(queryString);
 
             const taskLine = '- [ ] this is a task due 📅 2021-09-12 #inside_tag ⏫ #some/tags_with_underscore';
             const task = fromLine({
@@ -250,7 +250,7 @@ describe('Query parsing', () => {
         ];
         test.concurrent.each<string>(filters)('recognises %j', (filter) => {
             // Arrange
-            const query = new Query({ source: filter });
+            const query = new Query(filter);
 
             // Assert
             expect(query.error).toBeUndefined();
@@ -331,7 +331,7 @@ describe('Query parsing', () => {
         ];
         test.concurrent.each<string>(filters)('recognises %j', (filter) => {
             // Arrange
-            const query = new Query({ source: filter });
+            const query = new Query(filter);
 
             // Assert
             expect(query.error).toBeUndefined();
@@ -403,7 +403,7 @@ describe('Query parsing', () => {
         ];
         test.concurrent.each<string>(filters)('recognises %j', (filter) => {
             // Arrange
-            const query = new Query({ source: filter });
+            const query = new Query(filter);
 
             // Assert
             expect(query.error).toBeUndefined();
@@ -423,7 +423,7 @@ describe('Query parsing', () => {
         ];
         test.concurrent.each<string>(filters)('recognises %j', (filter) => {
             // Arrange
-            const query = new Query({ source: filter });
+            const query = new Query(filter);
 
             // Assert
             expect(query.error).toBeUndefined();
@@ -431,19 +431,19 @@ describe('Query parsing', () => {
     });
 
     it('should parse ambiguous sort by queries correctly', () => {
-        expect(new Query({ source: 'sort by status' }).sorting[0].property).toEqual('status');
-        expect(new Query({ source: 'sort by status.name' }).sorting[0].property).toEqual('status.name');
+        expect(new Query('sort by status').sorting[0].property).toEqual('status');
+        expect(new Query('sort by status.name').sorting[0].property).toEqual('status.name');
     });
 
     it('should parse ambiguous group by queries correctly', () => {
-        expect(new Query({ source: 'group by status' }).grouping[0].property).toEqual('status');
-        expect(new Query({ source: 'group by status.name' }).grouping[0].property).toEqual('status.name');
-        expect(new Query({ source: 'group by status.type' }).grouping[0].property).toEqual('status.type');
+        expect(new Query('group by status').grouping[0].property).toEqual('status');
+        expect(new Query('group by status.name').grouping[0].property).toEqual('status.name');
+        expect(new Query('group by status.type').grouping[0].property).toEqual('status.type');
     });
 
     describe('should include instruction in parsing error messages', () => {
         function getQueryError(source: string) {
-            return new Query({ source: source }).error;
+            return new Query(source).error;
         }
 
         it('for invalid regular expression filter', () => {
@@ -514,7 +514,7 @@ Problem line: "${source}"`);
             const path = 'a/b/path with space.md';
 
             // Act
-            const query = new Query({ source: rawQuery }, path);
+            const query = new Query(rawQuery, path);
 
             // Assert
             expect(query.source).toEqual(rawQuery); // Interesting that query.source still has the placeholder text
@@ -524,10 +524,10 @@ Problem line: "${source}"`);
 
         it('should report error if placeholders used without query location', () => {
             // Arrange
-            const input = 'path includes {{query.file.path}}';
+            const source = 'path includes {{query.file.path}}';
 
             // Act
-            const query = new Query({ source: input });
+            const query = new Query(source);
 
             // Assert
             expect(query).not.toBeValid();
@@ -542,11 +542,11 @@ Problem line: "${source}"`);
 
         it('should report error if non-existent placeholder used', () => {
             // Arrange
-            const input = 'path includes {{query.file.noSuchProperty}}';
+            const source = 'path includes {{query.file.noSuchProperty}}';
             const path = 'a/b/path with space.md';
 
             // Act
-            const query = new Query({ source: input }, path);
+            const query = new Query(source, path);
 
             // Assert
             expect(query).not.toBeValid();
@@ -606,8 +606,8 @@ describe('Query', () => {
                     createdDate: null,
                 }),
             ];
-            const input = 'path includes ab/c d';
-            const query = new Query({ source: input });
+            const source = 'path includes ab/c d';
+            const query = new Query(source);
 
             // Act
             let filteredTasks = [...tasks];
@@ -1033,7 +1033,7 @@ describe('Query', () => {
             // rather than a test of the **required** behaviour.
             // If the behaviour changes and '0' is returned instead of '-0',
             // that is absolutely fine.
-            const query = new Query({ source: 'sort by status reverse' });
+            const query = new Query('sort by status reverse');
             const sorter = query.sorting[0];
 
             expect(sorter!.comparator(todoTask, doneTask)).toEqual(1);
@@ -1045,8 +1045,8 @@ describe('Query', () => {
     describe('comments', () => {
         it('ignores comments', () => {
             // Arrange
-            const input = '# I am a comment, which will be ignored';
-            const query = new Query({ source: input });
+            const source = '# I am a comment, which will be ignored';
+            const query = new Query(source);
 
             // Assert
             expect(query.error).toBeUndefined();
@@ -1059,16 +1059,16 @@ describe('Query', () => {
         });
 
         it('should explain 0 filters', () => {
-            const input = '';
-            const query = new Query({ source: input });
+            const source = '';
+            const query = new Query(source);
 
             const expectedDisplayText = 'No filters supplied. All tasks will match the query.';
             expect(query.explainQuery()).toEqual(expectedDisplayText);
         });
 
         it('should explain 1 filter', () => {
-            const input = 'description includes hello';
-            const query = new Query({ source: input });
+            const source = 'description includes hello';
+            const query = new Query(source);
 
             const expectedDisplayText = `description includes hello
 `;
@@ -1076,8 +1076,8 @@ describe('Query', () => {
         });
 
         it('should explain 2 filters', () => {
-            const input = 'description includes hello\ndue 2012-01-23';
-            const query = new Query({ source: input });
+            const source = 'description includes hello\ndue 2012-01-23';
+            const query = new Query(source);
 
             const expectedDisplayText = `description includes hello
 
@@ -1088,8 +1088,8 @@ due 2012-01-23 =>
         });
 
         it('should include any error message in the explanation', () => {
-            const input = 'i am a nonsense query';
-            const query = new Query({ source: input });
+            const source = 'i am a nonsense query';
+            const query = new Query(source);
 
             const expectedDisplayText = `Query has an error:
 do not understand query
@@ -1099,8 +1099,8 @@ Problem line: "i am a nonsense query"
         });
 
         it('should explain limit 5', () => {
-            const input = 'limit 5';
-            const query = new Query({ source: input });
+            const source = 'limit 5';
+            const query = new Query(source);
 
             const expectedDisplayText = `No filters supplied. All tasks will match the query.
 
@@ -1110,8 +1110,8 @@ At most 5 tasks.
         });
 
         it('should explain limit 1', () => {
-            const input = 'limit 1';
-            const query = new Query({ source: input });
+            const source = 'limit 1';
+            const query = new Query(source);
 
             const expectedDisplayText = `No filters supplied. All tasks will match the query.
 
@@ -1121,8 +1121,8 @@ At most 1 task.
         });
 
         it('should explain limit 0', () => {
-            const input = 'limit 0';
-            const query = new Query({ source: input });
+            const source = 'limit 0';
+            const query = new Query(source);
 
             const expectedDisplayText = `No filters supplied. All tasks will match the query.
 
@@ -1132,8 +1132,8 @@ At most 0 tasks.
         });
 
         it('should explain group limit 4', () => {
-            const input = 'limit groups 4';
-            const query = new Query({ source: input });
+            const source = 'limit groups 4';
+            const query = new Query(source);
 
             const expectedDisplayText = `No filters supplied. All tasks will match the query.
 
@@ -1143,8 +1143,8 @@ At most 4 tasks per group (if any "group by" options are supplied).
         });
 
         it('should explain all limit options', () => {
-            const input = 'limit 127\nlimit groups to 8 tasks';
-            const query = new Query({ source: input });
+            const source = 'limit 127\nlimit groups to 8 tasks';
+            const query = new Query(source);
 
             const expectedDisplayText = `No filters supplied. All tasks will match the query.
 
@@ -1163,7 +1163,7 @@ At most 8 tasks per group (if any "group by" options are supplied).
         it('should default to ungrouped', () => {
             // Arrange
             const source = '';
-            const query = new Query({ source });
+            const query = new Query(source);
 
             // Assert
             expect(query.grouping.length).toEqual(0);
@@ -1171,8 +1171,8 @@ At most 8 tasks per group (if any "group by" options are supplied).
 
         it('should parse a supported group command without error', () => {
             // Arrange
-            const input = 'group by path';
-            const query = new Query({ source: input });
+            const source = 'group by path';
+            const query = new Query(source);
 
             // Assert
             expect(query.error).toBeUndefined();
@@ -1181,18 +1181,18 @@ At most 8 tasks per group (if any "group by" options are supplied).
 
         it('should log meaningful error for supported group type', () => {
             // Arrange
-            const input = 'group by xxxx';
-            const query = new Query({ source: input });
+            const source = 'group by xxxx';
+            const query = new Query(source);
 
             // Assert
             // Check that the error message contains the actual problem line
-            expect(query.error).toContain(input);
+            expect(query.error).toContain(source);
             expect(query.grouping.length).toEqual(0);
         });
 
         it('should apply limit correctly, after sorting tasks', () => {
             // Arrange
-            const input = `
+            const source = `
                 # sorting by status will move the incomplete tasks first
                 sort by status
 
@@ -1202,7 +1202,7 @@ At most 8 tasks per group (if any "group by" options are supplied).
                 # Apply a limit, to test which tasks make it to
                 limit 2
                 `;
-            const query = new Query({ source: input });
+            const query = new Query(source);
 
             const tasksAsMarkdown = `
 - [x] Task 1 - should not appear in output
@@ -1230,7 +1230,7 @@ At most 8 tasks per group (if any "group by" options are supplied).
 
         it('should apply group limit correctly, after sorting tasks', () => {
             // Arrange
-            const input = `
+            const source = `
                 # sorting by description will sort the tasks alphabetically
                 sort by description
 
@@ -1240,7 +1240,7 @@ At most 8 tasks per group (if any "group by" options are supplied).
                 # Apply a limit, to test which tasks make it to
                 limit groups 3
                 `;
-            const query = new Query({ source: input });
+            const query = new Query(source);
 
             const tasksAsMarkdown = `
 - [x] Task 2 - will be in the first group and sorted after next one
@@ -1276,8 +1276,8 @@ At most 8 tasks per group (if any "group by" options are supplied).
     describe('error handling', () => {
         it('should catch an exception that occurs during searching', () => {
             // Arrange
-            const input = 'filter by function wibble';
-            const query = new Query({ source: input });
+            const source = 'filter by function wibble';
+            const query = new Query(source);
             const task = TaskBuilder.createFullyPopulatedTask();
 
             // Act
diff --git a/tests/Query/Filter/DueDateField.test.ts b/tests/Query/Filter/DueDateField.test.ts
index 553900ab..f256e652 100644
--- a/tests/Query/Filter/DueDateField.test.ts
+++ b/tests/Query/Filter/DueDateField.test.ts
@@ -570,7 +570,7 @@ describe('due date', () => {
         keywords.forEach((keyword) => {
             const newRow = [keyword];
             dates.forEach((date) => {
-                const query = new Query({ source: `due ${keyword}${date}` });
+                const query = new Query(`due ${keyword}${date}`);
                 expect(query.error).toBeUndefined();
 
                 newRow.push(query.explainQuery().replace(/(\n)/g, '<br>'));
diff --git a/tests/Query/Filter/TextField.test.ts b/tests/Query/Filter/TextField.test.ts
index 80a0026b..5866e174 100644
--- a/tests/Query/Filter/TextField.test.ts
+++ b/tests/Query/Filter/TextField.test.ts
@@ -108,7 +108,7 @@ describe('explains regular expression searches', () => {
             tags regex does not match /(home|town)/
             tags regex matches /(home|pc_mac|town)/
 `;
-        const query = new Query({ source });
+        const query = new Query(source);
 
         // Assert
         verify(query.explainQuery() + `\nError: ${query.error ?? 'None'}`);
diff --git a/tests/TestingTools/ApprovalTestHelpers.ts b/tests/TestingTools/ApprovalTestHelpers.ts
index ec7a94d9..c4d66545 100644
--- a/tests/TestingTools/ApprovalTestHelpers.ts
+++ b/tests/TestingTools/ApprovalTestHelpers.ts
@@ -53,7 +53,7 @@ export function verifyQuery(instructions: string, options?: Options): void {
  * @param options
  */
 export function verifyQueryExplanation(instructions: string, options?: Options): void {
-    const query = new Query({ source: instructions });
+    const query = new Query(instructions);
     const explanation = query.explainQuery();
 
     expect(query.error).toBeUndefined();
diff --git a/tests/TestingTools/FilterTestHelpers.ts b/tests/TestingTools/FilterTestHelpers.ts
index d286b895..35d1ec7a 100644
--- a/tests/TestingTools/FilterTestHelpers.ts
+++ b/tests/TestingTools/FilterTestHelpers.ts
@@ -43,7 +43,7 @@ export function testTaskFilter(filter: FilterOrErrorMessage, task: Task, expecte
  */
 export function testTaskFilterViaQuery(filter: string, task: Task, expected: boolean) {
     // Arrange
-    const query = new Query({ source: filter });
+    const query = new Query(filter);
 
     const tasks = [task];
 
@@ -70,7 +70,7 @@ export function shouldSupportFiltering(
     expectedResult: Array<string>,
 ) {
     // Arrange
-    const query = new Query({ source: filters.join('\n') });
+    const query = new Query(filters.join('\n'));
 
     const tasks = allTaskLines.map(
         (taskLine) =>
diff --git a/tests/lib/QueryRendererHelper.test.ts b/tests/lib/QueryRendererHelper.test.ts
index 59ae6b51..ec419e14 100644
--- a/tests/lib/QueryRendererHelper.test.ts
+++ b/tests/lib/QueryRendererHelper.test.ts
@@ -12,7 +12,7 @@ window.moment = moment;
 describe('explain', () => {
     it('should explain a task', () => {
         const source = '';
-        const query = new Query({ source });
+        const query = new Query(source);
 
         const expectedDisplayText = `Explanation of this Tasks code block query:
 
@@ -26,7 +26,7 @@ No filters supplied. All tasks will match the query.`;
         globalFilter.set('#task');
 
         const source = '';
-        const query = new Query({ source });
+        const query = new Query(source);
 
         const expectedDisplayText = `Only tasks containing the global filter '#task'.
 
@@ -40,7 +40,7 @@ No filters supplied. All tasks will match the query.`;
         const globalQuery = new GlobalQuery('description includes hello');
 
         const source = '';
-        const query = new Query({ source });
+        const query = new Query(source);
 
         const expectedDisplayText = `Explanation of the global query:
 
@@ -59,7 +59,7 @@ No filters supplied. All tasks will match the query.`;
         globalFilter.set('#task');
 
         const source = '';
-        const query = new Query({ source });
+        const query = new Query(source);
 
         const expectedDisplayText = `Only tasks containing the global filter '#task'.
 
@@ -78,7 +78,7 @@ No filters supplied. All tasks will match the query.`;
         const globalQuery = new GlobalQuery('description includes hello');
 
         const source = 'ignore global query';
-        const query = new Query({ source });
+        const query = new Query(source);
 
         const expectedDisplayText = `Explanation of this Tasks code block query: