Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 38 additions & 0 deletions src/global.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,16 @@ import {RE2JS} from "re2js";
declare global {
interface String {
matchRE2JS(o: RE2JS): Array<string> | null;
matchAllRE2JS(o: RE2JS): IterableIterator<RegExpMatchAll>;
}
}

interface RegExpMatchAll extends Array<string> {
index?: number;
input?: string;
groups: Record<string, string> | undefined;
}

String.prototype.matchRE2JS = function (o: RE2JS): Array<string> | null {
let results: string[] | null = null;
const matcher = o.matcher(this.toString());
Expand All @@ -16,3 +24,33 @@ String.prototype.matchRE2JS = function (o: RE2JS): Array<string> | null {
}
return results;
};

String.prototype.matchAllRE2JS = function (o: RE2JS) {
const self = this.toString();
const matcher = o.matcher(self);

function* iterator (): IterableIterator<RegExpMatchAll> {
while (matcher.find()) {
const match: RegExpMatchAll = [] as unknown as RegExpMatchAll;
for (let i = 0; i <= matcher.groupCount(); i++) {
match.push(matcher.group(i));
}
match.index = matcher.groups[0];
match.input = self;

if (matcher.namedGroups && Object.keys(matcher.namedGroups).length > 0) {
const groups = Object.create(null);
for (const [name, value] of Object.entries(matcher.namedGroups as Record<string, number>)) {
groups[name] = matcher.group(value);
}
match.groups = groups;
} else {
match.groups = undefined;
}

yield match;
}
}

return iterator();
};
9 changes: 7 additions & 2 deletions src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,8 +82,13 @@ export class Utils {
static async getCoveragePercent (cwd: string, stateDir: string, coverageRegex: string, jobName: string) {
const content = await fs.readFile(`${cwd}/${stateDir}/output/${jobName}.log`, "utf8");

const regex = new RegExp(coverageRegex.replace(/^\//, "").replace(/\/$/, ""), "gm");
const matches = Array.from(content.matchAll(regex));
const regex = RE2JS.compile(
coverageRegex
.replace(/^\//, "")
.replace(/\/$/, ""),
RE2JS.MULTILINE,
);
const matches = Array.from(content.matchAllRE2JS(regex));
if (matches.length === 0) return "0";

const lastMatch = matches[matches.length - 1];
Expand Down
60 changes: 60 additions & 0 deletions tests/global.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import "../src/global";
import {RE2JS} from "re2js";

const tests = [
{
paragraph: "hello world",
regexp: "world",
description: "basic string pattern",
},
{
paragraph: "hello world",
regexp: "foo",
description: "no match found",
},
{
paragraph: "foo bar foo baz foo",
regexp: "foo",
description: "multiple matches",
},
{
paragraph: "abc123def456",
regexp: "(\\d+)",
description: "match with capturing group",
},
{
paragraph: "color: #ff0000; background: #00ff00;",
regexp: "#(?<hex>[0-9a-fA-F]{6})",
description: "named capturing group",
},
{
paragraph: "aaaa",
regexp: "aa",
description: "overlapping matches",
},
{
paragraph: "",
regexp: "a",
description: "empty string",
},
{
paragraph: "abc123abc",
regexp: "^abc|abc$",
description: "match at start or end",
},
{
paragraph: "a.b*c+d?",
regexp: "\\.",
description: "special character dot",
},
];

describe("matchAllRE2JS should behave similarly to matchAll", () => {
tests.forEach((t) => {
test(t.description, () => {
const matchAll = Array.from(t.paragraph.matchAll(new RegExp(t.regexp, "g")));
const matchAllRE2JS = Array.from(t.paragraph.matchAllRE2JS(RE2JS.compile(t.regexp)));
expect(matchAllRE2JS).toStrictEqual(matchAll);
});
});
});
5 changes: 5 additions & 0 deletions tests/test-cases/coverage/.gitlab-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,8 @@ import.meta.jest:
coverage: /All files.*?\|.*?\|.*?([\d\.]+)/
script:
- echo "All files | 99.3 | 97.91 | 100 | 100 | "

pcre regex:
coverage: /(?i)total.*? (100(?:\.0+)?\%|[1-9]?\d(?:\.\d+)?\%)$/
script:
- echo "TOTAL 18 0 100%"
12 changes: 12 additions & 0 deletions tests/test-cases/coverage/integration.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,15 @@ test("coverage <import.meta.jest>", async () => {
const expected = [chalk`{black.bgGreenBright PASS } {blueBright import.meta.jest} 97.91% {gray coverage}`];
expect(writeStreams.stdoutLines).toEqual(expect.arrayContaining(expected));
});

test("coverage <pcre regex>", async () => {
const writeStreams = new WriteStreamsMock();
await handler({
cwd: "tests/test-cases/coverage",
job: ["pcre regex"],
noColor: true,
}, writeStreams);

const expected = [chalk`{black.bgGreenBright PASS } {blueBright pcre regex} 100% {gray coverage}`];
expect(writeStreams.stdoutLines).toEqual(expect.arrayContaining(expected));
});