Repository: obsidian-tasks-group/obsidian-tasks
Pull request #2137 (2023-07-16 18:01:51)

fix: Report invalid regex flags - likely a missing slash


<!--- Provide a general summary of your changes in the Title above -->

# Description

Report any invalid regex flags as errors in the query.

This might happen in the case where the final closing slash is missing from the filter.

<!--- Describe your changes in detail -->

## Motivation and Context

<!--- Why is this change required? What problem does it solve? -->
<!--- If it fixes an open issue, please link to the issue here. -->

I want to report any regex errors to the user, rather than ignoring them as previously, because they generally are caused by a missing backslash in the query.

## How has this been tested?

- Running and updating existing tests
- Adding a new test
- Exploratory testing in the demo vault.

<!--- Please describe in detail how you tested your changes. -->
<!--- Include details of your testing environment, tests ran to see how -->
<!--- your change affects other areas of the code, etc. -->

## Screenshots (if appropriate)

## Types of changes

<!--- What types of changes does your code introduce? Put an `x` in all the boxes that apply: -->

Changes visible to users:

- [x] **Bug fix** (prefix: `fix` - non-breaking change which fixes an issue)

Internal changes:

- [x] **Tests** (prefix: `test` - additions and improvements to unit tests and the smoke tests)

## Checklist

<!--- Go over all the following points, and put an `x` in all the boxes that apply. -->
<!--- If you're unsure about any of these, don't hesitate to ask. We're here to help! -->

- [x] My code follows the code style of this project and passes `yarn run lint`.
- [ ] My change requires a change to the documentation.
- [ ] I have [updated the documentation](https://publish.obsidian.md/tasks-contributing/Documentation/About+Documentation) accordingly.
- [x] My change has adequate [Unit Test coverage](https://publish.obsidian.md/tasks-contributing/Testing/About+Testing).

## Terms

<!--
By submitting this pull request, you must agree to follow our
[contributing guide](https://publish.obsidian.md/tasks-contributing) and
[Code of Conduct](https://github.com/obsidian-tasks-group/obsidian-tasks/blob/main/CODE_OF_CONDUCT.md).
Put an x in the boxes to confirm you agree.
-->

- [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/Query/Matchers/RegexMatcher.ts b/src/Query/Matchers/RegexMatcher.ts
index dd6693ac..51447856 100644
--- a/src/Query/Matchers/RegexMatcher.ts
+++ b/src/Query/Matchers/RegexMatcher.ts
@@ -27,7 +27,12 @@ export class RegexMatcher extends IStringMatcher {
      * @throws {SyntaxError} Throws an exception if there was an error in {@link regexInput}.
      */
     public static validateAndConstruct(regexInput: string): RegexMatcher | null {
-        const regexPattern = /^\/(.+)\/([igmu]*)/;
+        // This expression has two parts.
+        // 1. The regex source:  Match every character from the start of the line to
+        //                       just before the final forward slash ('/').
+        // 2. The flags, if any: Match every character after the last slash,
+        //                       to the end of the line.
+        const regexPattern = /^\/(.+)\/([^/]*)$/;
         const query = regexInput.match(regexPattern);
 
         if (query !== null) {


Test patch:
diff --git a/tests/Query/Matchers/RegexMatcher.test.ts b/tests/Query/Matchers/RegexMatcher.test.ts
index 288dc0b4..521169bd 100644
--- a/tests/Query/Matchers/RegexMatcher.test.ts
+++ b/tests/Query/Matchers/RegexMatcher.test.ts
@@ -61,7 +61,7 @@ describe('RegexMatcher flags', () => {
         expect(matcher!.regex.flags).toEqual('gim');
     });
 
-    it.failing('should reject invalid "x" flag', () => {
+    it('should reject invalid "x" flag', () => {
         const t = () => {
             RegexMatcher.validateAndConstruct('/expression/x');
         };
@@ -69,6 +69,14 @@ describe('RegexMatcher flags', () => {
         expect(t).toThrowError("Invalid flags supplied to RegExp constructor 'x'");
     });
 
+    it('should treat any text after last slash as flags', () => {
+        const t = () => {
+            RegexMatcher.validateAndConstruct('/root/sub-folder/sub-sub-folder/filename.md');
+        };
+        expect(t).toThrow(SyntaxError);
+        expect(t).toThrowError("Invalid flags supplied to RegExp constructor 'filename.md'");
+    });
+
     it('should reject duplicate "ii" flag', () => {
         const t = () => {
             RegexMatcher.validateAndConstruct('/expression/ii');