graphql-language-service-server
Version:
Server process backing the GraphQL Language Service
82 lines (73 loc) • 2.22 kB
text/typescript
import { parse, compileScript, SFCScriptBlock } from 'vue/compiler-sfc';
import { RangeMapper, SourceParser } from './types';
import { Position, Range } from 'graphql-language-service';
import { BlockStatement, Statement } from '@babel/types';
type ParseVueSFCResult =
| { type: 'error'; errors: Error[] }
| {
type: 'ok';
scriptOffset: number;
scriptSetupAst?: Statement[];
scriptAst?: Statement[];
};
export function parseVueSFC(source: string): ParseVueSFCResult {
const { errors, descriptor } = parse(source);
if (errors.length !== 0) {
return { type: 'error', errors };
}
let scriptBlock: SFCScriptBlock | null = null;
try {
scriptBlock = compileScript(descriptor, { id: 'foobar' });
} catch (error) {
if (
error instanceof Error &&
error.message === '[@vue/compiler-sfc] SFC contains no <script> tags.'
) {
return {
type: 'ok',
scriptSetupAst: [],
scriptAst: [],
scriptOffset: 0,
};
}
return { type: 'error', errors: [error as Error] };
}
return {
type: 'ok',
scriptOffset: scriptBlock.loc.start.line - 1,
scriptSetupAst: scriptBlock.scriptSetupAst,
scriptAst: scriptBlock.scriptAst as BlockStatement[],
};
}
export const vueParser: SourceParser = (text, uri, logger) => {
const asts = [];
const parseVueSFCResult = parseVueSFC(text);
if (parseVueSFCResult.type === 'error') {
logger.info(
`Could not parse the vue file at ${uri} to extract the graphql tags:`,
);
for (const error of parseVueSFCResult.errors) {
logger.info(String(error));
}
return null;
}
if (parseVueSFCResult.scriptAst !== undefined) {
asts.push(...parseVueSFCResult.scriptAst);
}
if (parseVueSFCResult.scriptSetupAst !== undefined) {
asts.push(...parseVueSFCResult.scriptSetupAst);
}
const rangeMapper: RangeMapper = range => {
return new Range(
new Position(
range.start.line + parseVueSFCResult.scriptOffset,
range.start.character,
),
new Position(
range.end.line + parseVueSFCResult.scriptOffset,
range.end.character,
),
);
};
return { asts, rangeMapper };
};