• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

SAP / ui5-linter / 11818212773

13 Nov 2024 01:24PM CUT coverage: 82.058% (+1.8%) from 80.287%
11818212773

Pull #327

github

web-flow
Merge eb2eebb35 into a024d44ca
Pull Request #327: feat: Add ui5lint-disable directives

1893 of 2438 branches covered (77.65%)

Branch coverage included in aggregate %.

117 of 121 new or added lines in 9 files covered. (96.69%)

5 existing lines in 1 file now uncovered.

2717 of 3180 relevant lines covered (85.44%)

2620.54 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

4.55
/src/formatter/coverage.ts
1
import path from "node:path";
2
import {
3
        LintResult,
4
        CoverageInfo,
5
        CoverageCategory,
6
} from "../linter/LinterContext.js";
7
import {readFile} from "fs/promises";
8
import {LintMessageSeverity} from "../linter/messages.js";
9

10
const visualizedSpace = "\u00b7";
3✔
11
const visualizedTab = "\u00bb";
3✔
12
const visualizedTabs: string[] = [];
3✔
13

14
function formatSeverity(severity: LintMessageSeverity) {
15
        if (severity === LintMessageSeverity.Error) {
×
16
                return "error";
×
17
        } else if (severity === LintMessageSeverity.Warning) {
×
18
                return "warning";
×
19
        } else {
20
                throw new Error(`Unknown severity: ${LintMessageSeverity[severity]}`);
×
21
        }
22
}
23

24
function expandTabs(line: string, tabsize = 4) {
×
25
        let last = 0;
×
26
        let length = 0;
×
27
        return line.replace(/[ \t]/g, function (tab, offset) {
×
28
                length += offset - last;
×
29
                if (tab === "\t") {
×
30
                        const n = tabsize - length % tabsize;
×
31
                        length += n;
×
32
                        last++;
×
33
                        return visualizedTabs[n] ?? (visualizedTabs[n] = visualizedTab.padEnd(n, " "));
×
34
                }
35
                length++;
×
36
                last++;
×
37
                return visualizedSpace;
×
38
        });
39
}
40

41
function escape(str: string) {
42
        return str.replace(/&/g, "&amp;").replace(/</g, "&lt;");
×
43
}
44

45
export class Coverage {
46
        #buffer = "";
×
47

48
        async format(lintResults: LintResult[]) {
49
                this.#writeln(`<!DOCTYPE html>
×
50
<html lang="en">
51
<head>
52
        <meta charset="UTF-8">
53
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
54
        <title>UI5Lint Coverage Report ${new Date().toLocaleString()}</title>
55
        <style>
56
        html {
57
                font-family: Arial, sans-serif;
58
                font-size: 1em;
59
        }
60
        .file {
61
                margin-bottom: 2rem;
62
        }
63
        .codeline {
64
                padding-left: 1rem;
65
                font-family: monospace;
66
        }
67
        .codeline .line {
68
                text-align: right;
69
                padding-right: 1rem;
70
                width: 5ex;
71
                display: inline-block;
72
        }
73
        .codeline.has-messages .line {
74
                background-color: red;
75
                color: white;
76
        }
77
        .codeline .code {
78
                white-space: pre;
79
        }
80
        .codeline.has-messages .code {
81
                color: red;
82
        }
83
        .codeline .messages {
84
                background-color: red;
85
                color: white;
86
        }
87
        .codeline.no-coverage .line {
88
                background-color: grey;
89
                color: white;
90
        }
91
        .codeline.no-coverage .code {
92
                color: grey;
93
        }
94
        </style>
95
</head>
96
<body>`);
97

98
                for (const {filePath, messages, coverageInfo} of lintResults) {
×
99
                        const fileContent = await readFile(filePath, {encoding: "utf-8"});
×
100
                        const relativeFilePath = path.relative(process.cwd(), filePath);
×
101

102
                        this.#writeln(`<div class="file"><span>${escape(relativeFilePath)}</span>`);
×
103

104
                        fileContent.split("\n").forEach((code, i) => {
×
105
                                const line = i + 1;
×
106
                                this.#renderLine(
×
107
                                        expandTabs(code), line,
108
                                        messages.filter((msg) => msg.line === line),
×
109
                                        coverageInfo.filter(
110
                                                (info) => info.line === line && info.category === CoverageCategory.CallExpressionUnknownType
×
111
                                        )
112
                                );
113
                        });
114

115
                        this.#writeln(`</div>`);
×
116
                }
117

118
                this.#writeln(
×
119
                        `        </body>
120
</html>`);
121

122
                return this.#buffer;
×
123
        }
124

125
        #renderLine(code: string, line: number, messages: LintResult["messages"], coverageInfo: CoverageInfo[]) {
126
                const classes = ["codeline"];
×
127
                if (messages.length) {
×
128
                        classes.push("has-messages");
×
129
                } else if (coverageInfo.length) {
×
130
                        classes.push("no-coverage");
×
131
                }
132

133
                this.#writeln(`<div class="${classes.join(" ")}">`);
×
134

135
                this.#writeln(`<span class="line">${line}</span>`);
×
136
                this.#writeln(`<span class="code">${escape(code)}</span>`);
×
137

138
                if (messages.length) {
×
139
                        this.#writeln(`<span class="messages">${escape(
×
140
                                messages.map(
141
                                        (msg) => `${formatSeverity(msg.severity)} ${msg.message}`
×
142
                                ).join(" & ")
143
                        )}</span>`);
144
                }
145

146
                this.#writeln(`</div>`);
×
147
        }
148

149
        // eslint-disable-next-line no-unused-private-class-members
150
        #write(str: string) {
151
                this.#buffer += str;
×
152
        }
153

154
        #writeln(str: string) {
155
                this.#buffer += str + "\n";
×
156
        }
157
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc