Skip to content

Commit

Permalink
Merge pull request #7 from Blissful89/feature/add-custom-ignore-matcher
Browse files Browse the repository at this point in the history
Add custom ignore matcher
  • Loading branch information
rehlma authored Nov 20, 2024
2 parents a0b3691 + 0765907 commit c0adc82
Show file tree
Hide file tree
Showing 6 changed files with 119 additions and 21 deletions.
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,10 @@ You can configure the action further by providing inputs:
comment. Use `{todo}` to insert the Todo content
- `custom_todo_matcher`: (**optional**) Add custom comment indicators to match
TODOs. Default matches `//`, `*` and `#` followed by `TODO` or `FIXME`.
- `custom_ignore_matcher`: (**optional**) Add custom regex to ignore TODOs that
match in the same line. Example: Setting
`custom_ignore_matcher: "/.*ignore.*/"` will ignore TODOs like
`// TODO ignore`.

```yaml
steps:
Expand Down
63 changes: 63 additions & 0 deletions __test__/todo-finder.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -301,3 +301,66 @@ describe('custom todo matcher', () => {
expect(fileTodos).toEqual(expectedTodos)
})
})

describe('custom ignore matcher', () => {
it('should ignore matches', () => {
const customIgnoreMatcher = 'comment'
const fileTodos = findTodos(
testData.mixedTodoDiff,
[],
undefined,
customIgnoreMatcher
)

const expectedTodos: Todo[] = [
{
filename: 'README.md',
line: 31,
content: 'TODO here',
isAdded: true
},
{
filename: 'lib/second.js',
line: 26,
content: 'TODO - upper case with much space',
isAdded: true
},
{
filename: 'lib/second.js',
line: 27,
content: 'todo - lower case with space',
isAdded: true
},
{
filename: 'lib/second.js',
line: 28,
content: 'todo - lower case no space',
isAdded: true
}
]

const expectedIgnoredTodos: Todo[] = [
{
filename: 'lib/first.js',
line: 21,
content: 'TODO removed comment',
isAdded: false
},
{
filename: 'lib/second.js',
line: 30,
content: 'todo comment',
isAdded: true
},
{
filename: 'lib/second.js',
line: 33,
content: 'todo - In comment block',
isAdded: true
}
]

expect(fileTodos).toEqual(expectedTodos)
expect(fileTodos).not.toContain(expectedIgnoredTodos)
})
})
26 changes: 16 additions & 10 deletions dist/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -29330,6 +29330,7 @@ function run() {
const commentBodyTemplate = core.getInput('comment_body');
const commentCheckboxTemplate = core.getInput('comment_checkbox');
const customTodoMatcher = core.getInput('custom_todo_matcher');
const customIgnoreMather = core.getInput('custom_ignore_matcher');
const octokit = github.getOctokit(token);
const botName = 'github-actions[bot]';
const pr = github.context.payload.pull_request;
Expand All @@ -29348,7 +29349,7 @@ function run() {
}
else if (commentOnTodo) {
const prDiff = yield getPrDiff(octokit, pr.base.sha, pr.head.sha);
const todos = (0, todo_finder_1.findTodos)(prDiff, excludePatterns, customTodoMatcher);
const todos = (0, todo_finder_1.findTodos)(prDiff, excludePatterns, customTodoMatcher, customIgnoreMather);
console.log('Todos:', JSON.stringify(todos));
yield commentPr(octokit, pr.number, botName, todos, commentBodyTemplate, commentCheckboxTemplate);
}
Expand Down Expand Up @@ -29508,7 +29509,7 @@ function getTodosForDiff(pat, owner, repo, base, head) {
basehead: `${base}...${head}`
});
const prDiff = ((_a = response === null || response === void 0 ? void 0 : response.data) === null || _a === void 0 ? void 0 : _a.files) || [];
const todos = (0, todo_finder_1.findTodos)(prDiff, [], '{}');
const todos = (0, todo_finder_1.findTodos)(prDiff, [], '{}', '');
console.log('Todos:', JSON.stringify(todos));
});
}
Expand All @@ -29525,7 +29526,7 @@ exports.getTodosForDiff = getTodosForDiff;
Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.findTodos = void 0;
const minimatch_1 = __nccwpck_require__(4501);
function findTodos(prDiff, exclude = [], customTodoMatcherString = '{}') {
function findTodos(prDiff, exclude = [], customTodoMatcherString = '{}', customIgnoreMatcherString = '') {
// Find first number in string
const firstAddedLineRegex = /\+(\d+)/;
const firstRemovedLineRegex = /-(\d+)/;
Expand Down Expand Up @@ -29579,7 +29580,7 @@ function findTodos(prDiff, exclude = [], customTodoMatcherString = '{}') {
for (const line of lines) {
const isAdded = line.startsWith('+');
const isDeleted = line.startsWith('-');
const todo = getTodoIfFound(line, customMatcher);
const todo = getTodoIfFound(line, customMatcher, customIgnoreMatcherString);
if (isDeleted) {
if (todo !== undefined) {
todos.push({
Expand Down Expand Up @@ -29624,16 +29625,16 @@ function getTodoMatcherForFile(filename, customTodoMatcherString) {
}
return customMatcher;
}
function getTodoIfFound(line, customMatcher = []) {
const regex = new RegExp(buildTodoMatcher(customMatcher), 'i');
function getTodoIfFound(line, customMatcher = [], customIgnoreMatcher) {
const regex = new RegExp(buildTodoMatcher(customMatcher, customIgnoreMatcher), 'i');
const match = line.match(regex);
if (match === undefined || match === null || (match === null || match === void 0 ? void 0 : match.length) === 0)
return;
// remove html closing comment tag if present
const todo = match[1].replace('-->', '').trim();
return todo;
}
function buildTodoMatcher(customMatcher) {
function buildTodoMatcher(customMatcher, customIgnoreMatcher) {
let todoMatcher;
if (customMatcher.length === 0) {
// default todo matcher
Expand All @@ -29657,7 +29658,7 @@ function buildTodoMatcher(customMatcher) {
'$',
'.'
];
const escapedPatterns = todoMatcher.map(pattern => {
const escapePattern = (pattern) => {
let escapedPattern = '';
for (const char of pattern) {
if (needToEscape.includes(char)) {
Expand All @@ -29668,8 +29669,13 @@ function buildTodoMatcher(customMatcher) {
}
}
return escapedPattern;
});
const regex = `(?:${escapedPatterns.join('|')}).*?(TODO.*|FIXME.*)`;
};
const escapedTodoPatterns = todoMatcher.map(matcher => escapePattern(matcher));
const escapedIgnorePatterns = escapePattern(customIgnoreMatcher);
const ignoreRegex = customIgnoreMatcher
? `(?!.*${escapedIgnorePatterns}.*)`
: '';
const regex = `(?:${escapedTodoPatterns.join('|')})${ignoreRegex}.*?(TODO.*|FIXME.*)`;
return regex;
}

Expand Down
2 changes: 1 addition & 1 deletion dist/index.js.map

Large diffs are not rendered by default.

10 changes: 8 additions & 2 deletions src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ export async function run(): Promise<void> {
const commentBodyTemplate = core.getInput('comment_body')
const commentCheckboxTemplate = core.getInput('comment_checkbox')
const customTodoMatcher = core.getInput('custom_todo_matcher')
const customIgnoreMather = core.getInput('custom_ignore_matcher')

const octokit = github.getOctokit(token)
const botName = 'github-actions[bot]'
Expand All @@ -38,7 +39,12 @@ export async function run(): Promise<void> {
} else if (commentOnTodo) {
const prDiff = await getPrDiff(octokit, pr.base.sha, pr.head.sha)

const todos = findTodos(prDiff, excludePatterns, customTodoMatcher)
const todos = findTodos(
prDiff,
excludePatterns,
customTodoMatcher,
customIgnoreMather
)
console.log('Todos:', JSON.stringify(todos))
await commentPr(
octokit,
Expand Down Expand Up @@ -239,6 +245,6 @@ export async function getTodosForDiff(

const prDiff = response?.data?.files || []

const todos = findTodos(prDiff, [], '{}')
const todos = findTodos(prDiff, [], '{}', '')
console.log('Todos:', JSON.stringify(todos))
}
35 changes: 27 additions & 8 deletions src/todo-finder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ import { minimatch } from 'minimatch'
export function findTodos(
prDiff: PrDiff,
exclude: string[] = [],
customTodoMatcherString = '{}'
customTodoMatcherString = '{}',
customIgnoreMatcherString = ''
): Todo[] {
// Find first number in string
const firstAddedLineRegex = /\+(\d+)/
Expand Down Expand Up @@ -81,7 +82,11 @@ export function findTodos(
const isAdded = line.startsWith('+')
const isDeleted = line.startsWith('-')

const todo = getTodoIfFound(line, customMatcher)
const todo = getTodoIfFound(
line,
customMatcher,
customIgnoreMatcherString
)

if (isDeleted) {
if (todo !== undefined) {
Expand Down Expand Up @@ -133,17 +138,24 @@ function getTodoMatcherForFile(

function getTodoIfFound(
line: string,
customMatcher: string[] = []
customMatcher: string[] = [],
customIgnoreMatcher: string
): string | undefined {
const regex = new RegExp(buildTodoMatcher(customMatcher), 'i')
const regex = new RegExp(
buildTodoMatcher(customMatcher, customIgnoreMatcher),
'i'
)
const match = line.match(regex)
if (match === undefined || match === null || match?.length === 0) return
// remove html closing comment tag if present
const todo = match[1].replace('-->', '').trim()
return todo
}

function buildTodoMatcher(customMatcher: string[]): string {
function buildTodoMatcher(
customMatcher: string[],
customIgnoreMatcher: string
): string {
let todoMatcher: string[]
if (customMatcher.length === 0) {
// default todo matcher
Expand All @@ -168,7 +180,7 @@ function buildTodoMatcher(customMatcher: string[]): string {
'.'
]

const escapedPatterns = todoMatcher.map(pattern => {
const escapePattern = (pattern: string): string => {
let escapedPattern = ''
for (const char of pattern) {
if (needToEscape.includes(char)) {
Expand All @@ -178,8 +190,15 @@ function buildTodoMatcher(customMatcher: string[]): string {
}
}
return escapedPattern
})
}

const escapedTodoPatterns = todoMatcher.map(matcher => escapePattern(matcher))
const escapedIgnorePatterns = escapePattern(customIgnoreMatcher)

const ignoreRegex = customIgnoreMatcher
? `(?!.*${escapedIgnorePatterns}.*)`
: ''

const regex = `(?:${escapedPatterns.join('|')}).*?(TODO.*|FIXME.*)`
const regex = `(?:${escapedTodoPatterns.join('|')})${ignoreRegex}.*?(TODO.*|FIXME.*)`
return regex
}

0 comments on commit c0adc82

Please sign in to comment.