Skip to content

Commit

Permalink
pass around compressed spans so that we do unused directive check mor…
Browse files Browse the repository at this point in the history
…e efficiently
  • Loading branch information
gabritto committed Mar 28, 2024
1 parent 63c543d commit b51921d
Show file tree
Hide file tree
Showing 4 changed files with 19 additions and 15 deletions.
26 changes: 17 additions & 9 deletions src/compiler/program.ts
Original file line number Diff line number Diff line change
Expand Up @@ -305,7 +305,6 @@ import {
sys,
System,
targetOptionDeclaration,
textRangeContainsTextRange,
toFileNameLowerCase,
tokenToString,
toPath as ts_toPath,
Expand All @@ -323,6 +322,8 @@ import {
WriteFileCallback,
WriteFileCallbackData,
writeFileEnsuringDirectories,
TextSpan,
textSpanContainsTextRange,
} from "./_namespaces/ts";
import * as performance from "./_namespaces/ts.performance";

Expand Down Expand Up @@ -2799,10 +2800,10 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg
return getDiagnosticsHelper(sourceFile, getSyntacticDiagnosticsForFile, cancellationToken);
}

function getSemanticDiagnostics(sourceFile?: SourceFile, cancellationToken?: CancellationToken, nodesToCheck?: Node[]): readonly Diagnostic[] {
function getSemanticDiagnostics(sourceFile?: SourceFile, cancellationToken?: CancellationToken, nodesToCheck?: Node[], nodesToCheckSpans?: TextSpan[]): readonly Diagnostic[] {
return getDiagnosticsHelper(
sourceFile,
(sourceFile, cancellationToken) => getSemanticDiagnosticsForFile(sourceFile, cancellationToken, nodesToCheck),
(sourceFile, cancellationToken) => getSemanticDiagnosticsForFile(sourceFile, cancellationToken, nodesToCheck, nodesToCheckSpans),
cancellationToken,
);
}
Expand All @@ -2814,7 +2815,11 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg
}

function getBindAndCheckDiagnostics(sourceFile: SourceFile, cancellationToken?: CancellationToken): readonly Diagnostic[] {
return getBindAndCheckDiagnosticsForFile(sourceFile, cancellationToken, /*nodesToCheck*/ undefined);
return getBindAndCheckDiagnosticsForFile(
sourceFile,
cancellationToken,
/*nodesToCheck*/ undefined,
/*nodesToCheckSpans*/ undefined);
}

function getProgramDiagnostics(sourceFile: SourceFile): readonly Diagnostic[] {
Expand Down Expand Up @@ -2872,9 +2877,10 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg
sourceFile: SourceFile,
cancellationToken: CancellationToken | undefined,
nodesToCheck: Node[] | undefined,
nodesToCheckSpans: TextSpan[] | undefined,
): readonly Diagnostic[] {
return concatenate(
filterSemanticDiagnostics(getBindAndCheckDiagnosticsForFile(sourceFile, cancellationToken, nodesToCheck), options),
filterSemanticDiagnostics(getBindAndCheckDiagnosticsForFile(sourceFile, cancellationToken, nodesToCheck, nodesToCheckSpans), options),
getProgramDiagnostics(sourceFile),
);
}
Expand All @@ -2883,9 +2889,10 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg
sourceFile: SourceFile,
cancellationToken: CancellationToken | undefined,
nodesToCheck: Node[] | undefined,
nodesToCheckSpans: TextSpan[] | undefined,
): readonly Diagnostic[] {
if (nodesToCheck) {
return getBindAndCheckDiagnosticsForFileNoCache(sourceFile, cancellationToken, nodesToCheck);
return getBindAndCheckDiagnosticsForFileNoCache(sourceFile, cancellationToken, nodesToCheck, nodesToCheckSpans);
}
return getAndCacheDiagnostics(sourceFile, cancellationToken, cachedBindAndCheckDiagnosticsForFile, getBindAndCheckDiagnosticsForFileNoCache);
}
Expand All @@ -2894,6 +2901,7 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg
sourceFile: SourceFile,
cancellationToken: CancellationToken | undefined,
nodesToCheck?: Node[],
nodesToCheckSpans?: TextSpan[],
): readonly Diagnostic[] {
return runWithCancellationToken(() => {
if (skipTypeChecking(sourceFile, options, program)) {
Expand Down Expand Up @@ -2922,11 +2930,11 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg
checkDiagnostics = filter(checkDiagnostics, d => plainJSErrors.has(d.code));
}
// skip ts-expect-error errors in plain JS files, and skip JSDoc errors except in checked JS
return getMergedBindAndCheckDiagnostics(sourceFile, includeBindAndCheckDiagnostics && !isPlainJs, nodesToCheck, bindDiagnostics, checkDiagnostics, isCheckJs ? sourceFile.jsDocDiagnostics : undefined);
return getMergedBindAndCheckDiagnostics(sourceFile, includeBindAndCheckDiagnostics && !isPlainJs, nodesToCheckSpans, bindDiagnostics, checkDiagnostics, isCheckJs ? sourceFile.jsDocDiagnostics : undefined);
});
}

function getMergedBindAndCheckDiagnostics(sourceFile: SourceFile, includeBindAndCheckDiagnostics: boolean, nodesToCheck: Node[] | undefined, ...allDiagnostics: (readonly Diagnostic[] | undefined)[]) {
function getMergedBindAndCheckDiagnostics(sourceFile: SourceFile, includeBindAndCheckDiagnostics: boolean, nodesToCheckSpans: TextSpan[] | undefined, ...allDiagnostics: (readonly Diagnostic[] | undefined)[]) {
const flatDiagnostics = flatten(allDiagnostics);
if (!includeBindAndCheckDiagnostics || !sourceFile.commentDirectives?.length) {
return flatDiagnostics;
Expand All @@ -2935,7 +2943,7 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg
const { diagnostics, directives } = getDiagnosticsWithPrecedingDirectives(sourceFile, sourceFile.commentDirectives, flatDiagnostics);

for (const errorExpectation of directives.getUnusedExpectations()) {
if (!nodesToCheck || nodesToCheck.some(node => textRangeContainsTextRange(node, errorExpectation.range))) {
if (!nodesToCheckSpans || nodesToCheckSpans.some(span => textSpanContainsTextRange(span, errorExpectation.range))) {
diagnostics.push(createDiagnosticForRange(sourceFile, errorExpectation.range, Diagnostics.Unused_ts_expect_error_directive));
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/compiler/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4630,7 +4630,7 @@ export interface Program extends ScriptReferenceHost {
getGlobalDiagnostics(cancellationToken?: CancellationToken): readonly Diagnostic[];
getSyntacticDiagnostics(sourceFile?: SourceFile, cancellationToken?: CancellationToken): readonly DiagnosticWithLocation[];
/** The first time this is called without `nodesToCheck`, it will return global diagnostics (no location). */
getSemanticDiagnostics(sourceFile?: SourceFile, cancellationToken?: CancellationToken, nodesToCheck?: Node[]): readonly Diagnostic[];
getSemanticDiagnostics(sourceFile?: SourceFile, cancellationToken?: CancellationToken, nodesToCheck?: Node[], nodesToCheckSpans?: TextSpan[]): readonly Diagnostic[];
getDeclarationDiagnostics(sourceFile?: SourceFile, cancellationToken?: CancellationToken): readonly DiagnosticWithLocation[];
getConfigFileParsingDiagnostics(): readonly Diagnostic[];
/** @internal */ getSuggestionDiagnostics(sourceFile: SourceFile, cancellationToken?: CancellationToken): readonly DiagnosticWithLocation[];
Expand Down
4 changes: 0 additions & 4 deletions src/compiler/utilitiesPublic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -349,10 +349,6 @@ export function textRangeContainsPositionInclusive(range: TextRange, position: n
return position >= range.pos && position <= range.end;
}

export function textRangeContainsTextRange(range: TextRange, otherRange: TextRange): boolean {
return otherRange.pos >= range.pos && otherRange.end <= range.end;
}

// Returns true if 'span' contains 'other'.
export function textSpanContainsTextSpan(span: TextSpan, other: TextSpan) {
return other.start >= span.start && textSpanEnd(other) <= textSpanEnd(span);
Expand Down
2 changes: 1 addition & 1 deletion src/services/services.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2021,7 +2021,7 @@ export function createLanguageService(
return undefined;
}
const checkedSpans = normalizeSpans(nodes.map(node => createTextSpanFromBounds(node.getFullStart(), node.getEnd())));
const semanticDiagnostics = program.getSemanticDiagnostics(targetSourceFile, cancellationToken, nodes);
const semanticDiagnostics = program.getSemanticDiagnostics(targetSourceFile, cancellationToken, nodes, checkedSpans);
return {
diagnostics: semanticDiagnostics.slice(),
spans: checkedSpans,
Expand Down

0 comments on commit b51921d

Please sign in to comment.