Line data Source code
1 : import { computeScriptReferenceReports, type ScriptReferenceReport } from './script_reference_check.js';
2 : import { sessionAnalysisSignature, type SessionScripts } from './session_scripts.js';
3 :
4 1 : function sameReport(l: ScriptReferenceReport, r: ScriptReferenceReport): boolean {
5 1 : return l.textVersion === r.textVersion
6 1 : && l.marks.length === r.marks.length
7 1 : && l.marks.every((m, i) => {
8 1 : const o = r.marks[i];
9 1 : return m.from === o.from && m.to === o.to && m.parameter === o.parameter && m.target === o.target
10 1 : && m.kind === o.kind && m.errors.length === o.errors.length && m.errors.every((e, j) => e === o.errors[j]);
11 1 : });
12 1 : }
13 :
14 : interface CachedCheck {
15 : signature: string;
16 : reports: Map<number, ScriptReferenceReport>;
17 : }
18 :
19 : /// The last check of every session, by session id
20 1 : const CHECKS = new Map<string, CachedCheck>();
21 :
22 : /// The checked script references of the scripts of a session, by script key. Checks again only when a name, a
23 : /// connection or an analysis of a script changed, a report that did not change keeps its identity.
24 1 : export function checkSessionScriptReferences(session: SessionScripts): Map<number, ScriptReferenceReport> {
25 1 : try {
26 1 : return checkSessionScriptReferencesOrThrow(session);
27 1 : } catch (e) {
28 1 : console.warn('cannot check the script references of the session', e);
29 1 : return NO_REPORTS;
30 1 : }
31 1 : }
32 :
33 1 : const NO_REPORTS = new Map<number, ScriptReferenceReport>();
34 :
35 1 : function checkSessionScriptReferencesOrThrow(session: SessionScripts): Map<number, ScriptReferenceReport> {
36 : // Sessions without the core, e.g. of tests, have no checks
37 1 : if (session.scriptOrder == null || session.scriptOrder.length === 0 || typeof session.instance?.checkScriptReferences !== 'function') {
38 1 : return NO_REPORTS;
39 : }
40 1 : const signature = sessionAnalysisSignature(session);
41 1 : const cached = CHECKS.get(session.sessionId);
42 1 : if (cached?.signature === signature) return cached.reports;
43 1 : const reports = computeScriptReferenceReports(session);
44 : // A script without a current analysis keeps its last report until it is analyzed again
45 1 : for (const [key, report] of cached?.reports ?? []) {
46 1 : const next = reports.get(key);
47 1 : if (next == null && session.scripts[key] != null) reports.set(key, report);
48 1 : else if (next != null && sameReport(next, report)) reports.set(key, report);
49 1 : }
50 1 : CHECKS.set(session.sessionId, { signature, reports });
51 1 : return reports;
52 1 : }
53 :
54 : /// Forget the check of a session
55 0 : export function forgetSessionScriptReferences(sessionId: string): void {
56 0 : CHECKS.delete(sessionId);
57 0 : }
|