Skip to content

Commit

Permalink
Add documentation for CATcher's parser (#1240)
Browse files Browse the repository at this point in the history
When CATcher's parsers were updated to use arcsecond, there was minimal
documentation within the codebase to explain how the parsers work. As
such, it was difficult to understand and maintain these parsers.

Let's add examples for each comment template and explain the parsers
that are more difficult to understand.
  • Loading branch information
luminousleek authored Apr 26, 2024
1 parent 9690676 commit c7461b2
Show file tree
Hide file tree
Showing 10 changed files with 288 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,31 @@ const { char, choice, coroutine, everyCharUntil, str, whitespace } = require('ar
const TEAM_RESPONSE_HEADER = "# Team's Response";
const DEFAULT_TEAM_RESPONSE = 'No details provided by team.';

/**
* Builds a parser for the team response section.
* Team response sections appear in both the Team Response and Tester Response comment templates.
* The format of the Team Response section is as follows
* # Team's response
*
* { team's response }
*
* { next header }
*
* A concrete example would be:
*
* # Team's response
*
* This not a bug, it's a feature
*
* ## Duplicate status (if any):
*
* This parser works by reading everything in between the Team's reponse header and the next header.
* The reason why this parser builder exists is because the next header is different in both comment templates.
* The next header in the Team Response comment is ## Duplicate status (if any):
* While the next header in the Tester Response comment is # Disputes
* @param nextHeader
* @returns a string containing the team response
*/
export function buildTeamResponseSectionParser(nextHeader: string) {
return coroutine(function* () {
yield str(TEAM_RESPONSE_HEADER);
Expand All @@ -12,6 +37,13 @@ export function buildTeamResponseSectionParser(nextHeader: string) {
});
}

/**
* Parses the checkbox and returns whether it is filled or not.
* Filled checkboxes look like this: - [x] { description }, e.g. - [x] I disagree
* Unfilled checkboxes look like thsi: - [ ] { description }
* @param description
* @returns true if the checkbox is filled, false otherwise
*/
export function buildCheckboxParser(description: string) {
return coroutine(function* () {
yield str('- [');
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,37 @@
/**
* An issue dispute section has the following format:
*
* ## :question: Issue { type of verification }
*
* ### Team says:
*
* { team's action that is being disputed }
*
* ### Tester says:
*
* { tester's objection }
*
* <catcher-end-of-segment><hr>
*
* A concrete example would be:
*
* ## :question: Issue type
*
* ### Team says:
*
* Team chose [`type.DocumentationBug`].
* Originally [`type.FunctionalityBug`].
*
* This use case is just not in the docs.
*
* ### Tester says:
*
* It's not a use case, it's a bug! This has nothing to do with the docs.
*
* <catcher-end-of-segment><hr>
*
*/

import { IssueDispute } from '../../issue-dispute.model';

const { coroutine, everyCharUntil, optionalWhitespace, str } = require('arcsecond');
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,21 @@
/**
* A Tutor Moderation section has this format:
*
* ## :question: Issue { type of verification }
* - [ ] Done
*
* { tutor response }
*
* <catcher-end-of-segment><hr>
*
* A concrete example would be:
*
* ## :question: Issue type
* - [x] Done
*
* I think it's all cool
*/

import { Checkbox } from '../../checkbox.model';
import { IssueDispute } from '../../issue-dispute.model';
import { buildCheckboxParser } from './common-parsers.model';
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,33 @@
/**
* A tester response section generally has this format (apart from the duplicate issue section)
*
* ## :question: Issue {type of verification}
*
* Team chose [{ team response }].
* Originally [{ tester response }].
*
* - [ ] I disagree
*
* **Reason for disagreement:**
* { disagreement reason }
*
* <catcher-end-of-segment><hr>
*
* A concrete example would be:
*
* ## :question: Issue severity
*
* Team chose [`severity.Low`].
* Originally [`severity.Medium`].
*
* - [x] I disagree
*
* **Reason for disagreement:**
* The team is silly and doesn't understand how bad this bug is!!!
*
* <catcher-end-of-segment><hr>
*/

import { buildCheckboxParser } from './common-parsers.model';

const {
Expand All @@ -24,6 +54,12 @@ const DUPLICATE_STATUS_MESSAGE =

export const DisagreeCheckboxParser = buildCheckboxParser(DISAGREE_CHECKBOX_DESCRIPTION);

/**
* This parser extracts the response for the item disagreed on.
* E.g. for [`severity.Low`], the category is 'severity' and the parser would return 'Low'
* @param category
* @returns a string indicating the response in that category
*/
function buildExtractResponseParser(category: string) {
return between(str('[`' + category + '.'))(str('`]'))(letters);
}
Expand All @@ -48,7 +84,21 @@ export const DisagreeReasonParser = coroutine(function* () {
return reasonForDisagreement.trim();
});

// Issue duplicate section has a different format than the other three
/**
* The duplicate issue section has a different format than the other three, which is below:
*
* ## :question: Issue duplicate status
*
* Team chose to mark this issue as a duplicate of another issue (as explained in the _**Team's response**_ above)
*
*
*
* - [ ] I disagree
*
* **Reason for disagreement:** [replace this with your explanation]
*
* <catcher-end-of-segment><hr>
*/
const DuplicateSectionParser = coroutine(function* () {
yield str('status');
yield whitespace;
Expand Down Expand Up @@ -93,7 +143,7 @@ export const TesterResponseSectionParser = coroutine(function* () {

const teamChose = yield teamResponseParser;
yield whitespace;
// response section does not have tester response
// response section does not have tester response, i.e. no "Originally [`response.Something`]"
const testerChose = yield possibly(testerResponseParser);
yield optionalWhitespace;

Expand Down
6 changes: 6 additions & 0 deletions src/app/core/models/templates/team-accepted-template.model.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
/**
* A Team Accepted comment has this format:
*
* Your response not required for this bug as the team has accepted the bug as it is.
*/

import { GithubComment } from '../github/github-comment.model';
import { Template } from './template.model';

Expand Down
19 changes: 19 additions & 0 deletions src/app/core/models/templates/team-response-template.model.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,22 @@
/**
* A Team Response comment has the following format:
*
* # Team's response
*
* { team's response }
*
* ## Duplicate status (if any):
* { duplicate issue number, or '--' if not a duplicate }
*
* A concrete example would be:
*
* # Team's response
*
* This is not a bug, it's a feature
*
* ## Duplicate status (if any):
* Duplicate of #42
*/
import { IssueComment } from '../comment.model';
import { GithubComment } from '../github/github-comment.model';
import { buildTeamResponseSectionParser } from './section-parsers/common-parsers.model';
Expand Down
4 changes: 4 additions & 0 deletions src/app/core/models/templates/template.model.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
/**
* Comment template formats can be found at https://catcher-org.github.io/dg/user-workflow.html
*/

import { GithubComment } from '../github/github-comment.model';

export abstract class Template {
Expand Down
50 changes: 50 additions & 0 deletions src/app/core/models/templates/tester-response-template.model.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,53 @@
/**
* A Tester Response comment has the following format:
*
* [IMPORTANT!: Please do not edit or reply to this comment using the GitHub UI. \
You can respond to it using CATcher during the next phase of the PE]
*
* # Team's response
*
* { team's response }
*
* # Items for the Tester to Verify
*
* { 1 or more Tester Response sections, see tester-response-section-parser.model.ts }
*
* A concrete example would be:
*
* [IMPORTANT!: Please do not edit or reply to this comment using the GitHub UI. \
You can respond to it using CATcher during the next phase of the PE]
*
* # Team's response
*
* This is not a bug, it's a feature
*
* # Items for the Tester to Verify
*
* ## :question: Issue type
*
* Team chose [`type.DocumentationBug`].
* Originally [`type.FunctionalityBug`].
*
* [x] - I disagree
*
* **Reason for disagreement:**
* It's not a use case, it's a bug! This has nothing to do with the docs.
*
* <catcher-end-of-segment><hr>
*
* ## :question: Issue severity
*
* Team chose [`severity.VeryLow`].
* Originally [`severity.High`].
*
* [x] - I disagree
*
* **Reason for disagreement:**
* You don't understand how frustrating this bug is!!
*
* <catcher-end-of-segment><hr>
*/

import { IssueComment } from '../comment.model';
import { GithubComment } from '../github/github-comment.model';
import { TesterResponse } from '../tester-response.model';
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,52 @@
/**
* A Tutor Moderation Issue comment has this format:
*
* # Issue Description
* { original issue description }
*
* # Team's Response
* { team's response}
*
* # Disputes
*
* { 1 or more Issue Dispute sections, see issue-dispute-section-parser.model.ts }
*
* A concrete example would be:
*
* # Issue Description
* This feature doesn't work when I enter this input!
*
* # Team's Response
* This is not a bug, it is a feature
*
* # Disputes
*
* ## :question: Issue type
*
* Team chose [`type.DocumentationBug`].
* Originally [`type.FunctionalityBug`].
*
* This use case is just not in the docs.
*
* ### Tester says:
*
* It's not a use case, it's a bug! This has nothing to do with the docs.
*
* <catcher-end-of-segment><hr>
*
* ## :question: Issue severity
*
* Team chose [`severity.VeryLow`].
* Originally [`severity.High`].
*
* This only affects users a tiny little bit.
*
* ### Tester says:
* You don't understand how frustrating this bug is!!
*
* <catcher-end-of-segment><hr>
*/

import { GithubIssue } from '../github/github-issue.model';
import { IssueDispute } from '../issue-dispute.model';
import { buildTeamResponseSectionParser } from './section-parsers/common-parsers.model';
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,27 @@
/**
* A Tutor Moderation Todo comment has this format:
*
* # Tutor Moderation
*
* { 1 or more Tutor Moderation sections, see moderation-section-parser.model.ts }
*
* A concrete example would be:
*
* # Tutor Moderation
*
* ## :question: Issue severity
* - [x] Done
*
* I think it is justified.
*
* <catcher-end-of-segment><hr>
*
* ## :question: Issue type
* - [ ] Done
*
* <catcher-end-of-segment><hr>
*/

import { IssueComment } from '../comment.model';
import { GithubComment } from '../github/github-comment.model';
import { IssueDispute } from '../issue-dispute.model';
Expand Down

0 comments on commit c7461b2

Please sign in to comment.