Skip to content

Commit

Permalink
Add TypeScript annotation parsing and improve annotation handling in …
Browse files Browse the repository at this point in the history
…tests
  • Loading branch information
pelikhan committed Sep 13, 2024
1 parent f6c4240 commit b936768
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 9 deletions.
19 changes: 18 additions & 1 deletion packages/core/src/annotations.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { parseAnnotations } from "./annotations"
import assert from "assert/strict"

describe("annotations", () => {
test("error", () => {
test("github", () => {
const output = `
::error file=packages/core/src/github.ts,line=71,endLine=71,code=concatenation_override::The change on line 71 may lead to the original \`text\` content being overridden instead of appending the footer. Consider using \`text = appendGeneratedComment(script, info, text)\` to ensure the original text is preserved and the footer is appended. 😇
Expand All @@ -25,4 +25,21 @@ describe("annotations", () => {
"The change on line 71 may lead to the original `text` content being overridden instead of appending the footer. Consider using `text = appendGeneratedComment(script, info, text)` to ensure the original text is preserved and the footer is appended. 😇"
)
})

test("tsc", () => {
const output = `
src/annotations.ts:11:28 - error TS1005: ',' expected.
`

const diags = parseAnnotations(output)
// console.log(diags)
assert.strictEqual(diags.length, 1)
assert.strictEqual(diags[0].severity, "error")
assert.strictEqual(diags[0].filename, "src/annotations.ts")
assert.strictEqual(diags[0].range[0][0], 10)
assert.strictEqual(diags[0].range[1][0], 27)
assert.strictEqual(diags[0].code, "TS1005")
assert.strictEqual(diags[0].message, "',' expected.")
})
})
35 changes: 27 additions & 8 deletions packages/core/src/annotations.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/workflow-commands-for-github-actions#setting-an-error-message
const GITHUB_ANNOTATIONS_RX =
/^\s*::(?<severity>notice|warning|error)\s*file=(?<file>[^,]+),\s*line=(?<line>\d+),\s*endLine=(?<endLine>\d+)\s*(,\s*code=(?<code>[^,:]+)?\s*)?::(?<message>.*)$/gim
// ##vso[task.logissue type=warning;sourcepath=consoleap
Expand All @@ -6,18 +7,38 @@ const GITHUB_ANNOTATIONS_RX =
const AZURE_DEVOPS_ANNOTATIONS_RX =
/^\s*##vso\[task.logissue\s+type=(?<severity>error|warning);sourcepath=(?<file>);linenumber=(?<line>\d+)(;code=(?<code>\d+);)?[^\]]*\](?<message>.*)$/gim

// https://code.visualstudio.com/docs/editor/tasks#_background-watching-tasks
const TYPESCRIPT_ANNOTATIONS_RX =
/^(?<file>[^:\s].*?):(?<line>\d+)(?::(?<endLine>\d+))?(?::\d+)?\s+-\s+(?<severity>error|warning)\s+(?<code>[^:]+)\s*:\s*(?<message>.*)$/gim

/**
* Matches ::(notice|warning|error) file=<filename>,line=<start line>::<message>
* Matches TypeScript, GitHub Actions and Azure DevOps annotations
* @param line
* @link https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/workflow-commands-for-github-actions#setting-an-error-message
*/
export function parseAnnotations(text: string): Diagnostic[] {
if (!text) return []
const sevMap: Record<string, DiagnosticSeverity> = {
["info"]: "info",
["notice"]: "info",
["warning"]: "warning",
["error"]: "error",
}
const annotations: Record<string, Diagnostic> = {}
const annotations = new Set<Diagnostic>()
for (const m of text.matchAll(TYPESCRIPT_ANNOTATIONS_RX)) {
const { file, line, endLine, severity, code, message } = m.groups
const annotation: Diagnostic = {
severity: sevMap[severity],
filename: file,
range: [
[parseInt(line) - 1, 0],
[parseInt(endLine) - 1, Number.MAX_VALUE],
],
message,
code,
}
annotations.add(annotation)
}

Check failure on line 41 in packages/core/src/annotations.ts

View workflow job for this annotation

GitHub Actions / build

There is no error handling for the case when the severity is not found in the sevMap. This could lead to undefined behavior if an unexpected severity value is encountered. Consider adding error handling or a default case. 😊
text.replace(
GITHUB_ANNOTATIONS_RX,
(_, severity, file, line, endLine, __, code, message) => {
Expand All @@ -31,12 +52,11 @@ export function parseAnnotations(text: string): Diagnostic[] {
message,
code,
}
const key = JSON.stringify(annotation)
annotations[key] = annotation
annotations.add(annotation)
return ""
}
)
text?.replace(
text.replace(
AZURE_DEVOPS_ANNOTATIONS_RX,
(_, severity, file, line, __, code, message) => {
const annotation: Diagnostic = {
Expand All @@ -49,12 +69,11 @@ export function parseAnnotations(text: string): Diagnostic[] {
message,
code,
}
const key = JSON.stringify(annotation)
annotations[key] = annotation
annotations.add(annotation)
return ""
}
)

Check failure on line 75 in packages/core/src/annotations.ts

View workflow job for this annotation

GitHub Actions / build

The code for parsing GitHub and Azure DevOps annotations is almost identical. Consider refactoring this into a separate function to avoid code duplication. This will make the code easier to maintain and less prone to errors. 😇
return Object.values(annotations)
return Array.from(annotations.values())
}

export function convertDiagnosticToGitHubActionCommand(d: Diagnostic) {
Expand Down

0 comments on commit b936768

Please sign in to comment.