11import { SymbolKind , TextDocument } from 'vscode' ;
2- import { METHOD_KINDS , getClassesAndMethodsContainedInRange , getClassesAndMethodsOfDocument , logger } from '../utils' ;
2+ import { METHOD_KINDS , getSymbolsContainedInRange , getSymbolsOfDocument , logger } from '../utils' ;
33import { Inspection } from './Inspection' ;
4- import * as crypto from "crypto" ;
54import { SymbolNode } from './SymbolNode' ;
65
76/**
87 * A map based cache for inspections of a document.
9- * format: `Map<documentKey, Map<symbolQualifiedName, [symbolVersionId , Inspection[]]`
8+ * format: `Map<documentKey, Map<symbolQualifiedName, [symbolSnapshotId , Inspection[]]`
109 */
11- const DOC_SYMBOL_VERSION_INSPECTIONS : Map < string , Map < string , [ string , Inspection [ ] ] > > = new Map ( ) ;
10+ const DOC_SYMBOL_SNAPSHOT_INSPECTIONS : Map < string , Map < string , [ string , Inspection [ ] ] > > = new Map ( ) ;
1211
1312export default class InspectionCache {
1413 /**
@@ -18,15 +17,14 @@ export default class InspectionCache {
1817 public static async hasCache ( document : TextDocument , symbol ?: SymbolNode ) : Promise < boolean > {
1918 const documentKey = document . uri . fsPath ;
2019 if ( ! symbol ) {
21- return DOC_SYMBOL_VERSION_INSPECTIONS . has ( documentKey ) ;
20+ return DOC_SYMBOL_SNAPSHOT_INSPECTIONS . has ( documentKey ) ;
2221 }
23- const symbolInspections = DOC_SYMBOL_VERSION_INSPECTIONS . get ( documentKey ) ;
22+ const symbolInspections = DOC_SYMBOL_SNAPSHOT_INSPECTIONS . get ( documentKey ) ;
2423 // check if the symbol or its contained symbols are cached
25- const symbols = await getClassesAndMethodsContainedInRange ( symbol . range , document ) ;
24+ const symbols = await getSymbolsContainedInRange ( symbol . range , document ) ;
2625 for ( const s of symbols ) {
27- const versionInspections = symbolInspections ?. get ( s . qualifiedName ) ;
28- const symbolVersionId = InspectionCache . calculateSymbolVersionId ( document , s ) ;
29- if ( versionInspections ?. [ 0 ] === symbolVersionId ) {
26+ const snapshotInspections = symbolInspections ?. get ( s . qualifiedName ) ;
27+ if ( snapshotInspections ?. [ 0 ] === s . snapshotId && snapshotInspections [ 1 ] . length > 0 ) {
3028 return true ;
3129 }
3230 }
@@ -39,7 +37,7 @@ export default class InspectionCache {
3937 * their content has changed.
4038 */
4139 public static async getCachedInspectionsOfDoc ( document : TextDocument ) : Promise < Inspection [ ] > {
42- const symbols : SymbolNode [ ] = await getClassesAndMethodsOfDocument ( document ) ;
40+ const symbols : SymbolNode [ ] = await getSymbolsOfDocument ( document ) ;
4341 const inspections : Inspection [ ] = [ ] ;
4442 // we don't get cached inspections directly from the cache, because we need to filter out outdated symbols
4543 for ( const symbol of symbols ) {
@@ -54,12 +52,11 @@ export default class InspectionCache {
5452 */
5553 public static getCachedInspectionsOfSymbol ( document : TextDocument , symbol : SymbolNode ) : Inspection [ ] {
5654 const documentKey = document . uri . fsPath ;
57- const symbolInspections = DOC_SYMBOL_VERSION_INSPECTIONS . get ( documentKey ) ;
58- const versionInspections = symbolInspections ?. get ( symbol . qualifiedName ) ;
59- const symbolVersionId = InspectionCache . calculateSymbolVersionId ( document , symbol ) ;
60- if ( versionInspections ?. [ 0 ] === symbolVersionId ) {
55+ const symbolInspections = DOC_SYMBOL_SNAPSHOT_INSPECTIONS . get ( documentKey ) ;
56+ const snapshotInspections = symbolInspections ?. get ( symbol . qualifiedName ) ;
57+ if ( snapshotInspections ?. [ 0 ] === symbol . snapshotId ) {
6158 logger . debug ( `cache hit for ${ SymbolKind [ symbol . kind ] } ${ symbol . qualifiedName } of ${ document . uri . fsPath } ` ) ;
62- const inspections = versionInspections [ 1 ] ;
59+ const inspections = snapshotInspections [ 1 ] ;
6360 inspections . forEach ( s => {
6461 s . document = document ;
6562 s . problem . position . line = s . problem . position . relativeLine + symbol . range . start . line ;
@@ -78,7 +75,7 @@ export default class InspectionCache {
7875 return isMethod ?
7976 // NOTE: method inspections are inspections whose `position.line` is within the method's range
8077 inspectionLine >= symbol . range . start . line && inspectionLine <= symbol . range . end . line :
81- // NOTE: class inspections are inspections whose `position.line` is exactly the first line number of the class
78+ // NOTE: class/field inspections are inspections whose `position.line` is exactly the first line number of the class/field
8279 inspectionLine === symbol . range . start . line ;
8380 } ) ;
8481 // re-calculate `relativeLine` of method inspections, `relativeLine` is the relative line number to the start of the method
@@ -93,13 +90,13 @@ export default class InspectionCache {
9390 */
9491 public static invalidateInspectionCache ( document ?: TextDocument , symbol ?: SymbolNode , inspeciton ?: Inspection ) : void {
9592 if ( ! document ) {
96- DOC_SYMBOL_VERSION_INSPECTIONS . clear ( ) ;
93+ DOC_SYMBOL_SNAPSHOT_INSPECTIONS . clear ( ) ;
9794 } else if ( ! symbol ) {
9895 const documentKey = document . uri . fsPath ;
99- DOC_SYMBOL_VERSION_INSPECTIONS . delete ( documentKey ) ;
96+ DOC_SYMBOL_SNAPSHOT_INSPECTIONS . delete ( documentKey ) ;
10097 } else if ( ! inspeciton ) {
10198 const documentKey = document . uri . fsPath ;
102- const symbolInspections = DOC_SYMBOL_VERSION_INSPECTIONS . get ( documentKey ) ;
99+ const symbolInspections = DOC_SYMBOL_SNAPSHOT_INSPECTIONS . get ( documentKey ) ;
103100 // remove the cached inspections of the symbol
104101 symbolInspections ?. delete ( symbol . qualifiedName ) ;
105102 // remove the cached inspections of contained symbols
@@ -110,11 +107,10 @@ export default class InspectionCache {
110107 } ) ;
111108 } else {
112109 const documentKey = document . uri . fsPath ;
113- const symbolInspections = DOC_SYMBOL_VERSION_INSPECTIONS . get ( documentKey ) ;
114- const versionInspections = symbolInspections ?. get ( symbol . qualifiedName ) ;
115- const symbolVersionId = InspectionCache . calculateSymbolVersionId ( document , symbol ) ;
116- if ( versionInspections ?. [ 0 ] === symbolVersionId ) {
117- const inspections = versionInspections [ 1 ] ;
110+ const symbolInspections = DOC_SYMBOL_SNAPSHOT_INSPECTIONS . get ( documentKey ) ;
111+ const snapshotInspections = symbolInspections ?. get ( symbol . qualifiedName ) ;
112+ if ( snapshotInspections ?. [ 0 ] === symbol . snapshotId ) {
113+ const inspections = snapshotInspections [ 1 ] ;
118114 // remove the inspection
119115 inspections . splice ( inspections . indexOf ( inspeciton ) , 1 ) ;
120116 }
@@ -124,22 +120,13 @@ export default class InspectionCache {
124120 private static cacheSymbolInspections ( document : TextDocument , symbol : SymbolNode , inspections : Inspection [ ] ) : void {
125121 logger . debug ( `cache ${ inspections . length } inspections for ${ SymbolKind [ symbol . kind ] } ${ symbol . qualifiedName } of ${ document . uri . fsPath } ` ) ;
126122 const documentKey = document . uri . fsPath ;
127- const symbolVersionId = InspectionCache . calculateSymbolVersionId ( document , symbol ) ;
128- const cachedSymbolInspections = DOC_SYMBOL_VERSION_INSPECTIONS . get ( documentKey ) ?? new Map ( ) ;
123+ const cachedSymbolInspections = DOC_SYMBOL_SNAPSHOT_INSPECTIONS . get ( documentKey ) ?? new Map ( ) ;
129124 inspections . forEach ( s => {
130125 s . document = document ;
131126 s . symbol = symbol ;
132127 } ) ;
133128 // use qualified name to prevent conflicts between symbols with the same signature in same document
134- cachedSymbolInspections . set ( symbol . qualifiedName , [ symbolVersionId , inspections ] ) ;
135- DOC_SYMBOL_VERSION_INSPECTIONS . set ( documentKey , cachedSymbolInspections ) ;
136- }
137-
138- /**
139- * generate a unique id for the symbol based on its content, so that we can detect if the symbol has changed
140- */
141- private static calculateSymbolVersionId ( document : TextDocument , symbol : SymbolNode ) : string {
142- const body = document . getText ( symbol . range ) ;
143- return crypto . createHash ( 'md5' ) . update ( body ) . digest ( "hex" )
129+ cachedSymbolInspections . set ( symbol . qualifiedName , [ symbol . snapshotId , inspections ] ) ;
130+ DOC_SYMBOL_SNAPSHOT_INSPECTIONS . set ( documentKey , cachedSymbolInspections ) ;
144131 }
145132}
0 commit comments