Skip to content

Commit

Permalink
fix: Ensure cli-reporter displays the correct message. (#1774)
Browse files Browse the repository at this point in the history
* fix: Ensure cli-reporter displays the correct message.
  - Use a substitution function to ensure Issue formatting is correct.
* Update snapshots impacted.
  • Loading branch information
Jason3S authored Sep 26, 2021
1 parent 5a9542e commit c0aaf45
Show file tree
Hide file tree
Showing 6 changed files with 117 additions and 29 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ Lines:
./documents/Analysis II/Analysis-II.tex:535:56 - Unknown word (Differentation) -- der Reihenfolge der Differentation.
./documents/Analysis II/Analysis-II.tex:66:110 - Unknown word (Skalarmultiplikation) -- blichen Addition und Skalarmultiplikation ein reeller Vektorraum
./documents/Analysis II/Analysis-II.tex:739:73 - Unknown word (Linearform) -- ax\ (x \in \MdR^n)$ (Linearform). $f'(x) = a\ \forall
./documents/Analysis II/Analysis-II.tex:758:249 - Unknown word (Matrizenprodukt) -- cdot f'(x_0)\text{ (Matrizenprodukt)}$
./documents/Analysis II/Analysis-II.tex:758:249 - Unknown word (Matrizenprodukt) -- cdot f'(x_0)\text{ (Matrizenprodukt)}$$
./documents/Analysis II/Analysis-II.tex:784:25 - Unknown word (reellwertig) -- g(x_1,\ldots,x_m)$ reellwertig,
./documents/Analysis II/Analysis-II.tex:833:10 - Unknown word (Differenzierbarkeitseigenschaften) -- \chapter{Differenzierbarkeitseigenschaften reellwertiger Funktionen
./documents/Analysis II/Analysis-II.tex:833:44 - Unknown word (reellwertiger) -- erenzierbarkeitseigenschaften reellwertiger Funktionen}
Expand Down Expand Up @@ -1011,7 +1011,7 @@ Lines:
./documents/kit-muendlich-proplan/kit-muendlich-proplan.tex:222:41 - Unknown word (Wegesuche) -- das bei der kürzesten Wegesuche sehen.
./documents/kit-muendlich-proplan/kit-muendlich-proplan.tex:228:51 - Unknown word (wernn) -- $A$ nach $E$ kürzer wernn man direkt von $B$ nach
./documents/kit-muendlich-proplan/kit-muendlich-proplan.tex:232:69 - Unknown word (Rückwärtsrekursiv) -- Horizont). Dabei geht man Rückwärtsrekursiv
./documents/kit-muendlich-proplan/kit-muendlich-proplan.tex:251:213 - Unknown word (aktionsabhängige) -- k \cdot a_k}_{\text{aktionsabhängige Kosten}} \right )$
./documents/kit-muendlich-proplan/kit-muendlich-proplan.tex:251:213 - Unknown word (aktionsabhängige) -- k \cdot a_k}_{\text{aktionsabhängige Kosten}} \right )$$
./documents/kit-muendlich-proplan/kit-muendlich-proplan.tex:254:60 - Unknown word (Riccati) -- durch die iterativen Riccati-Gleichungen
./documents/kit-muendlich-proplan/kit-muendlich-proplan.tex:262:38 - Unknown word (POMDPs) -- gut. Kommen wir zu POMDPs. Wie löst man die?
./documents/kit-muendlich-proplan/kit-muendlich-proplan.tex:264:81 - Unknown word (Funktionsapproximatoren) -- sbare Spezialfälle, Funktionsapproximatoren, Änderung der Optimierung
Expand Down
8 changes: 4 additions & 4 deletions integration-tests/snapshots/django/django/snapshot.txt
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ Lines:
./django/conf/global_settings.py:146:27 - Unknown word (Udmurt) -- udm', gettext_noop('Udmurt')),
./django/conf/global_settings.py:248:25 - Unknown word (Naver) -- re.compile(r'^NaverBot.*'),
./django/conf/global_settings.py:251:25 - Unknown word (sohu) -- re.compile(r'^sohu-search'),
./django/conf/global_settings.py:262:25 - Unknown word (favicon) -- re.compile(r'^/favicon.ico),
./django/conf/global_settings.py:262:25 - Unknown word (favicon) -- re.compile(r'^/favicon.ico$'),
./django/conf/global_settings.py:264:25 - Unknown word (phpmyadmin) -- re.compile(r'^/phpmyadmin/'),
./django/conf/global_settings.py:328:10 - Unknown word (myproject) -- # (i.e. "myproject.locale" for myproject
./django/conf/global_settings.py:463:24 - Unknown word (sessionid) -- SESSION_COOKIE_NAME = 'sessionid'
Expand Down Expand Up @@ -274,7 +274,7 @@ Lines:
./django/contrib/gis/geoip2/base.py:160:28 - Unknown word (gethostbyname) -- query = socket.gethostbyname(query)
./django/contrib/gis/geoip2/base.py:195:9 - Unknown word (cdict) -- cdict = self.city(query)
./django/contrib/gis/geoip2/base.py:26:16 - Unknown word (MMAP) -- # Try MODE_MMAP_EXT, MODE_MMAP, MODE
./django/contrib/gis/geometry.py:14:8 - Unknown word (ACEGIMLONPSRUTYZ) -- r'[ACEGIMLONPSRUTYZ\d,\.\-\+\(\) ]+),
./django/contrib/gis/geometry.py:14:8 - Unknown word (ACEGIMLONPSRUTYZ) -- r'[ACEGIMLONPSRUTYZ\d,\.\-\+\(\) ]+)$',
./django/contrib/gis/geos/__init__.py:12:7 - Unknown word (libgeos) -- from .libgeos import geos_version
./django/contrib/gis/geos/collections.py:59:25 - Unknown word (geomn) -- return capi.get_geomn(self.ptr, index)
./django/contrib/gis/geos/coordseq.py:87:17 - Unknown word (setx) -- capi.cs_setx(self.ptr, index, value
Expand Down Expand Up @@ -534,7 +534,7 @@ Lines:
./django/db/backends/postgresql/client.py:49:18 - Unknown word (PGSSLCERT) -- env['PGSSLCERT'] = str(sslcert)
./django/db/backends/postgresql/client.py:51:18 - Unknown word (PGSSLKEY) -- env['PGSSLKEY'] = str(sslkey)
./django/db/backends/postgresql/creation.py:47:38 - Unknown word (pgcode) -- getattr(e.__cause__, 'pgcode', '') != errorcodes
./django/db/backends/postgresql/features.py:43:17 - Unknown word (plpgsql) -- $ LANGUAGE plpgsql;"""
./django/db/backends/postgresql/features.py:43:17 - Unknown word (plpgsql) -- $$ LANGUAGE plpgsql;"""
./django/db/backends/postgresql/introspection.py:105:39 - Unknown word (refobjid) -- JOIN pg_depend d ON d.refobjid = s.oid AND d.refclassid
./django/db/backends/postgresql/introspection.py:105:62 - Unknown word (refclassid) -- refobjid = s.oid AND d.refclassid = 'pg_class'::regclass
./django/db/backends/postgresql/introspection.py:106:50 - Unknown word (objid) -- attrdef ad ON ad.oid = d.objid AND d.classid = 'pg
Expand Down Expand Up @@ -1983,7 +1983,7 @@ Lines:
./tests/template_tests/test_loaders.py:172:37 - Unknown word (Straße) -- self.source_checker(['/Straße']) as check_sources
./tests/template_tests/test_response.py:192:14 - Unknown word (repickling) -- def test_repickling(self):
./tests/template_tests/tests.py:37:48 - Unknown word (strack) -- should keep original strack trace when reraising
./tests/template_tests/urls.py:17:16 - Unknown word (Юникод) -- re_path(r'^Юникод/(\w+)/, views.client
./tests/template_tests/urls.py:17:16 - Unknown word (Юникод) -- re_path(r'^Юникод/(\w+)/$', views.client
./tests/test_client/tests.py:155:11 - Unknown word (Vendored) -- # Vendored tree JSON content types
./tests/test_client/tests.py:595:67 - Unknown word (nopassword) -- otheruser', password='nopassword')
./tests/test_client/tests.py:782:49 - Unknown word (descript) -- ValueError rather than a non-descript AssertionError.
Expand Down
2 changes: 1 addition & 1 deletion integration-tests/snapshots/mdx-js/mdx/snapshot.txt
Original file line number Diff line number Diff line change
Expand Up @@ -461,7 +461,7 @@ Lines:
./packages/remark-mdx/test/index.js:458:47 - Unknown word (tefg) -- Alpha <b c d="d"\t\tefg=\'e\'>charlie</b>.'
./packages/remark-mdx/test/index.js:880:59 - Unknown word (apos) -- can be used: &quot;, &apos;, &lt;, &gt;, &#x7B
./packages/vue/test/test.js:37:89 - Unknown word (vfiles) -- supports strings instead of vfiles for run.
./patches/react-server-dom-webpack+0.0.0-experimental-7ec4c5597.patch:13:10 - Unknown word (typeof) -- $typeof: MODULE_REFERENCE,
./patches/react-server-dom-webpack+0.0.0-experimental-7ec4c5597.patch:13:10 - Unknown word (typeof) -- $$typeof: MODULE_REFERENCE,
./patches/react-server-dom-webpack+0.0.0-experimental-7ec4c5597.patch:43:31 - Unknown word (deps) -- // TODO: Hook into deps instead of the target
./readme.md:104:5 - Unknown word (valign) -- <tr valign="middle">
./website/mdx-config.js:14:14 - Unknown word (Gemoji) -- import remarkGemoji from 'remark-gemoji
Expand Down
2 changes: 1 addition & 1 deletion packages/cspell-trie-lib/src/lib/suggest-en-a-star.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,7 @@ describe('Validate English Suggestions', () => {
suggestionTimeout
);
const elapsed = timer.elapsed();
expect(elapsed).toBeLessThan(suggestionTimeout * 2);
expect(elapsed).toBeLessThan(suggestionTimeout * 4);
},
timeout
);
Expand Down
61 changes: 61 additions & 0 deletions packages/cspell/src/cli-reporter.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import { __testing__, ReporterIssue } from './cli-reporter';

const { formatIssue } = __testing__;

const doc = `
This is a simple document with a bit of text.
It has more than one line.
$myPhpOffset := $row + $col;
$uri:$filename:$row:$col$padRowCol,$message,$text,$padContext,$contextLeft,$text,$contextRight,[$suggestions]
And some words to be used for some spelling issues.
There are many options.
`;

describe('cli-reporter', () => {
test.each`
issue | template | expected
${genIssue('line')} | ${''} | ${''}
${genIssue('line')} | ${'$row:$col:$text'} | ${'4:21:line'}
${genIssue('$col')} | ${'$row:$col:$text'} | ${'6:23:$col'}
${genIssue('$col')} | ${'$row:$col:$text - $contextFull'} | ${'6:23:$col - := $row + $col;'}
${genIssue('message')} | ${'$row:$col:$text - $contextFull'} | ${'8:36:message - adRowCol,$message,$text,$pa'}
${genIssue('used')} | ${'$contextLeft:$text:$contextRight - $contextFull'} | ${'rds to be :used: for some - rds to be used for some '}
`('formatIssue', ({ issue, template, expected }) => {
expect(formatIssue(template, issue, 200)).toBe(expected);
});
});

function genIssue(word: string): ReporterIssue {
const offset = doc.indexOf(word);
const text = word;
const beforeText = doc.slice(0, offset);
const prevLines = beforeText.split('\n');
const lines = doc.split('\n');
const row = prevLines.length;
const lineText = lines[row - 1];
const line = { offset: doc.indexOf(lineText), text: lineText };
const col = offset - line.offset;

const contextL = Math.max(0, col - 10);
const contextR = Math.min(lineText.length, col + text.length + 10);
const context = { offset: line.offset + contextL, text: line.text.slice(contextL, contextR) };

const issue: ReporterIssue = {
filename: 'path/filename',
offset,
uri: 'file://uri/path/filename',
context,
doc,
line,
col,
row,
text,
};

return issue;
}
69 changes: 48 additions & 21 deletions packages/cspell/src/cli-reporter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ const templateIssueWithContextWithSuggestions = `{green $filename}:{yellow $row:
const templateIssueLegacy = `${chalk.green('$filename')}[$row, $col]: $message: ${chalk.red('$text')}`;
const templateIssueWordsOnly = '$text';

export // Exported for testing.
interface ReporterIssue extends Issue {
filename: string;
}
Expand Down Expand Up @@ -136,7 +137,7 @@ export function getReporter(options: Options): CSpellReporter {
};
}

function formatIssue(templateStr: string, issue: ReporterIssue, maxIssueTextWidth: number) {
function formatIssue(templateStr: string, issue: ReporterIssue, maxIssueTextWidth: number): string {
function clean(t: string) {
return t.replace(/\s+/, ' ');
}
Expand All @@ -150,27 +151,24 @@ function formatIssue(templateStr: string, issue: ReporterIssue, maxIssueTextWidt
const padRowCol = ' '.repeat(Math.max(1, 8 - (rowText.length + colText.length)));
const suggestions = issue.suggestions?.join(', ') || '';
const message = issue.isFlagged ? '{yellow Forbidden word}' : 'Unknown word';

const substitutions = {
$col: colText,
$contextFull: contextFull,
$contextLeft: contextLeft,
$contextRight: contextRight,
$filename: filename,
$padContext: padContext,
$padRowCol: padRowCol,
$row: rowText,
$suggestions: suggestions,
$text: text,
$uri: uri,
};

const t = template(templateStr.replace(/\$message/g, message));
return (
chalk(t)
.replace(/\$\{col\}/g, colText)
.replace(/\$\{filename\}/g, filename)
.replace(/\$\{row\}/g, rowText)
.replace(/\$\{text\}/g, text)
.replace(/\$\{uri\}/g, uri)
.replace(/\$col/g, colText)
.replace(/\$filename/g, filename)
.replace(/\$padContext/g, padContext)
.replace(/\$padRowCol/g, padRowCol)
.replace(/\$row/g, rowText)
.replace(/\$suggestions/g, suggestions)
.replace(/\$text/g, text)
.replace(/\$uri/g, uri)
// Note: context substitution needs to be last to prevent accidental substitution.
.replace(/\$contextFull/g, contextFull)
.replace(/\$contextLeft/g, contextLeft)
.replace(/\$contextRight/g, contextRight)
);

return substitute(chalk(t), substitutions);
}

class TS extends Array<string> {
Expand All @@ -184,3 +182,32 @@ class TS extends Array<string> {
function template(s: string): TemplateStringsArray {
return new TS(s);
}

function substitute(text: string, substitutions: Record<string, string>): string {
type SubRange = [number, number, string];
const subs: SubRange[] = [];

for (const [match, replaceWith] of Object.entries(substitutions)) {
const len = match.length;
for (let i = text.indexOf(match); i >= 0; i = text.indexOf(match, i + 1)) {
subs.push([i, i + len, replaceWith]);
}
}

subs.sort((a, b) => a[0] - b[0]);

let i = 0;
function sub(r: SubRange): string {
const [a, b, t] = r;
const prefix = text.slice(i, a);
i = b;
return prefix + t;
}

const parts = subs.map(sub);
return parts.join('') + text.slice(i);
}

export const __testing__ = {
formatIssue,
};

0 comments on commit c0aaf45

Please sign in to comment.