All files / languages/linters xsd-any-uri-literal-linter.ts

100% Statements 12/12
90.9% Branches 10/11
100% Functions 1/1
100% Lines 12/12

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53                    20x                       236x 188x     48x 48x   48x 42x     6x 6x   6x 1x     5x                        
import { XSD } from '@faubulous/mentor-rdf';
import { IToken, RdfToken } from '@faubulous/mentor-rdf-parsers';
import { Diagnostic, DiagnosticSeverity } from 'vscode-languageserver/browser';
import { LintDiagnosticsContext } from '../linter-context';
import { Linter } from '../linter';
import { getIriFromToken, getUnquotedLiteralValue } from '@src/utilities';
 
/**
 * The diagnostic code for xsd:anyURI string literals that should be IRI references.
 */
export const XSD_ANY_URI_LITERAL_CODE = 'XsdAnyUriLiteral';
 
/**
 * Detects `"http(s)://..."^^xsd:anyURI` typed literals and suggests replacing them
 * with IRI references `<http(s)://...>`.
 *
 * This rule operates on the already-parsed token stream (specifically `DoubleCaret` tokens)
 * rather than running a regex over the raw text, reusing the same token iteration that
 * the language server performs for XSD datatype validation.
 */
export class XsdAnyUriLiteralLinter implements Linter {
	visitToken(context: LintDiagnosticsContext, token: IToken, index: number): Diagnostic[] {
		if (token.tokenType?.name !== RdfToken.DCARET.name || index < 1 || index >= context.tokens.length - 1) {
			return [];
		}
 
		const { document, tokens, prefixes } = context;
		const datatype = getIriFromToken(prefixes, tokens[index + 1]);
 
		if (datatype !== XSD.anyURI) {
			return [];
		}
 
		const valueToken = tokens[index - 1];
		const value = getUnquotedLiteralValue(valueToken);
 
		if (!/^https?:\/\//.test(value)) {
			return [];
		}
 
		return [{
			code: XSD_ANY_URI_LITERAL_CODE,
			severity: DiagnosticSeverity.Hint,
			message: `Use the IRI reference '<${value}>' instead of a typed string literal.`,
			source: 'Mentor',
			range: {
				start: document.positionAt(valueToken.startOffset),
				end: document.positionAt((tokens[index + 1].endOffset ?? tokens[index + 1].startOffset) + 1),
			}
		}];
	}
}