Skip to content

Commit 6c3101c

Browse files
authored
Merge pull request #3228 from obsidian-tasks-group/access-related-tasks
refactor: Add ListItem methods findClosestParentTask() and isTask()
2 parents babbe1d + 87abcd2 commit 6c3101c

File tree

5 files changed

+52
-26
lines changed

5 files changed

+52
-26
lines changed

src/Renderer/QueryResultsRenderer.ts

Lines changed: 2 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -28,23 +28,6 @@ export interface QueryRendererParameters {
2828
editTaskPencilClickHandler: EditButtonClickHandler;
2929
}
3030

31-
/**
32-
* We want this function to be a method of ListItem but that causes a circular dependency
33-
* which makes the plugin fail to load in Obsidian.
34-
*
35-
* Note: the tests are in ListItem.test.ts
36-
*
37-
* @param listItem
38-
*/
39-
export function findClosestParentTask(listItem: ListItem) {
40-
// Try to find the closest parent that is a task
41-
let closestParentTask = listItem.parent;
42-
while (closestParentTask !== null && !(closestParentTask instanceof Task)) {
43-
closestParentTask = closestParentTask.parent;
44-
}
45-
return closestParentTask;
46-
}
47-
4831
export class QueryResultsRenderer {
4932
/**
5033
* The complete text in the instruction block, such as:
@@ -274,7 +257,7 @@ export class QueryResultsRenderer {
274257
}
275258

276259
private willBeRenderedLater(listItem: ListItem, renderedListItems: Set<ListItem>, listItems: ListItem[]) {
277-
const closestParentTask = findClosestParentTask(listItem);
260+
const closestParentTask = listItem.findClosestParentTask();
278261
if (!closestParentTask) {
279262
return false;
280263
}
@@ -349,7 +332,7 @@ export class QueryResultsRenderer {
349332
await this.textRenderer(
350333
listItem.description,
351334
span,
352-
findClosestParentTask(listItem)?.path ?? '',
335+
listItem.findClosestParentTask()?.path ?? '',
353336
this.obsidianComponent,
354337
);
355338

src/Task/ListItem.ts

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { TaskRegularExpressions } from './TaskRegularExpressions';
2+
import type { Task } from './Task';
23

34
export class ListItem {
45
// The original line read from file.
@@ -46,6 +47,28 @@ export class ListItem {
4647
return this.parent === null;
4748
}
4849

50+
/**
51+
* Find to find the closest parent that is a {@link Task}
52+
*/
53+
public findClosestParentTask(): Task | null {
54+
let closestParentTask = this.parent;
55+
56+
while (closestParentTask !== null) {
57+
// Lazy load the Task class to avoid circular dependencies
58+
const { Task } = require('./Task');
59+
if (closestParentTask instanceof Task) {
60+
return closestParentTask as Task;
61+
}
62+
closestParentTask = closestParentTask.parent;
63+
}
64+
65+
return null;
66+
}
67+
68+
get isTask() {
69+
return false;
70+
}
71+
4972
/**
5073
* Compare all the fields in another ListItem, to detect any differences from this one.
5174
*

src/Task/Task.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -492,6 +492,15 @@ export class Task extends ListItem {
492492
return recurrenceOnNextLine ? potentiallyPrunedTasks.reverse() : potentiallyPrunedTasks;
493493
}
494494

495+
/**
496+
* Return whether this object is a {@link Task}.
497+
*
498+
* This is useful at run-time to discover whether a {@link ListItem} reference is in fact a {@link Task}.
499+
*/
500+
get isTask() {
501+
return true;
502+
}
503+
495504
/**
496505
* Return whether the task is considered done.
497506
* @returns true if the status type is {@link StatusType.DONE}, {@link StatusType.CANCELLED} or {@link StatusType.NON_TASK}, and false otherwise.

tests/Task/ListItem.test.ts

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ import { TaskLocation } from '../../src/Task/TaskLocation';
88
import { ListItem } from '../../src/Task/ListItem';
99
import { TaskBuilder } from '../TestingTools/TaskBuilder';
1010
import { fromLine } from '../TestingTools/TestHelpers';
11-
import { findClosestParentTask } from '../../src/Renderer/QueryResultsRenderer';
1211
import { createChildListItem } from './ListItemHelpers';
1312

1413
window.moment = moment;
@@ -80,6 +79,11 @@ describe('list item tests', () => {
8079
expect(child.isRoot).toEqual(false);
8180
});
8281

82+
it('should not be a task', () => {
83+
const listItem = new ListItem('- list item', null);
84+
expect(listItem.isTask).toBe(false);
85+
});
86+
8387
it.each([
8488
['- ', true],
8589
['* ', true],
@@ -107,19 +111,19 @@ describe('related items', () => {
107111
const item = new ListItem('- item', null);
108112
const childOfItem = new ListItem('- child of item', item);
109113

110-
expect(findClosestParentTask(task)).toEqual(null);
111-
expect(findClosestParentTask(item)).toEqual(null);
112-
expect(findClosestParentTask(childOfItem)).toEqual(null);
114+
expect(task.findClosestParentTask()).toEqual(null);
115+
expect(item.findClosestParentTask()).toEqual(null);
116+
expect(childOfItem.findClosestParentTask()).toEqual(null);
113117
});
114118

115119
it('should find the closest parent task', () => {
116120
const parentTask = fromLine({ line: '- [ ] task' });
117121
const child = new ListItem('- item', parentTask);
118122
const grandChild = new ListItem('- item', child);
119123

120-
expect(findClosestParentTask(parentTask)).toEqual(null);
121-
expect(findClosestParentTask(child)).toEqual(parentTask);
122-
expect(findClosestParentTask(grandChild)).toEqual(parentTask);
124+
expect(parentTask.findClosestParentTask()).toEqual(null);
125+
expect(child.findClosestParentTask()).toEqual(parentTask);
126+
expect(grandChild.findClosestParentTask()).toEqual(parentTask);
123127
});
124128
});
125129

tests/Task/Task.test.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,13 @@ describe('immutability', () => {
6767
});
6868
});
6969

70+
describe('list item-related tests', () => {
71+
it('should be a task', () => {
72+
const task = fromLine({ line: '- [ ] A Task' });
73+
expect(task.isTask).toBe(true);
74+
});
75+
});
76+
7077
describe('parsing', () => {
7178
it('parses a task from a line starting with hyphen', () => {
7279
// Arrange

0 commit comments

Comments
 (0)