cspell-grammar
Version:
Grammar parsing support for cspell
90 lines • 2.85 kB
JavaScript
import { opFlatten, opMap, pipe } from '@cspell/cspell-pipe/sync';
import { grammar } from '../../grammars/typescript.js';
import { appendMappedText } from '../../mappers/appendMappedText.js';
import { mapRawString } from '../../mappers/typescript.js';
import { compileGrammar } from '../../parser/grammar.js';
import { createParser } from '../../parser/parser.js';
import { ScopePool } from '../../parser/scope.js';
const tsGrammar = compileGrammar(grammar);
const pool = new ScopePool();
const useScope = new WeakMap();
function* transform(texts) {
for (const parsed of texts) {
if (doesScopeMatch(parsed.scope, 'constant.character.escape.ts')) {
const mapped = mapRawString(parsed.text);
const scope = parsed.scope ? pool.parseScope(parsed.scope) : undefined;
yield {
text: mapped.text,
scope: scope?.parent,
map: mapped.map,
range: parsed.range,
};
continue;
}
yield parsed;
}
}
function* mergeStringResults(results) {
let last;
for (const next of results) {
if (!doesScopeMatch(next.scope, 'string.')) {
if (last) {
yield last;
last = undefined;
}
yield next;
continue;
}
if (!last) {
last = next;
continue;
}
if (next.scope !== last.scope || last.range[1] !== next.range[0]) {
yield last;
last = next;
continue;
}
last = mergeParsedText(last, next);
}
if (last)
yield last;
}
function mergeParsedText(a, b) {
const abT = appendMappedText(a, b);
const ab = {
text: abT.text,
scope: a.scope,
range: [a.range[0], b.range[1]],
map: abT.map,
delegate: a.delegate,
};
return ab;
}
function filterScope(scope) {
const cached = useScope.get(scope);
if (cached !== undefined)
return cached;
const value = scope.value;
const use = !value.startsWith('punctuation') && !value.startsWith('keyword.');
useScope.set(scope, use);
return use;
}
function mapTokenizedLine(tl) {
return tl.tokens
.filter((t) => filterScope(t.scope))
.map((t) => ({
text: t.text,
range: [tl.offset + t.range[0], tl.offset + t.range[1]],
scope: t.scope,
}));
}
function mapTokenizedLines(itl) {
return pipe(itl, opMap(mapTokenizedLine), opFlatten(), transform, mergeStringResults);
}
export const parser = createParser(tsGrammar, 'typescript', mapTokenizedLines);
function doesScopeMatch(s, match) {
if (!s)
return false;
return typeof s === 'string' ? s.startsWith(match) : s.value.startsWith(match);
}
//# sourceMappingURL=TypeScriptParser.js.map