@@ -21,6 +21,10 @@ class CodeSimilarityCheck extends Check {
2121 static var SIMILAR_HASHES : Map <String , HashedCodeBlock > = new Map <String , HashedCodeBlock >();
2222 static var IDENTICAL_HASHES : Map <String , HashedCodeBlock > = new Map <String , HashedCodeBlock >();
2323 static var LOCK : Mutex = new Mutex ();
24+ #if use_similarity_ringbuffer
25+ static var FILE_RINGBUFFER : Array <String > = [];
26+ static var FILE_HASHES : Map <String , Array <CodeHashes >> = new Map <String , Array <CodeHashes >>();
27+ #end
2428
2529 /**
2630 severity level for identical code blocks
@@ -92,6 +96,9 @@ class CodeSimilarityCheck extends Check {
9296 startColumn : offsetToColumn (lineStart ),
9397 endColumn : offsetToColumn (lineEnd )
9498 }
99+ #if use_similarity_ringbuffer
100+ recordFileHashes (hashes , codeBlock );
101+ #end
95102
96103 if (hashes .tokenCount > thresholdIdentical ) {
97104 var existing : Null <HashedCodeBlock > = checkOrAddHash (hashes .identicalHash , codeBlock , IDENTICAL_HASHES );
@@ -117,11 +124,58 @@ class CodeSimilarityCheck extends Check {
117124 function checkOrAddHash (hash : String , codeBlock : HashedCodeBlock , hashTable : Map <String , HashedCodeBlock >): Null <HashedCodeBlock > {
118125 LOCK .acquire ();
119126 var existing : Null <HashedCodeBlock > = hashTable .get (hash );
120- if (existing == null ) hashTable .set (hash , codeBlock );
127+ if (existing == null ) {
128+ hashTable .set (hash , codeBlock );
129+ }
121130 LOCK .release ();
122131 return existing ;
123132 }
124133
134+ #if use_similarity_ringbuffer
135+ function recordFileHashes (hashes : CodeHashes , codeBlock : HashedCodeBlock ) {
136+ LOCK .acquire ();
137+ if (! FILE_RINGBUFFER .contains (codeBlock .fileName )) FILE_RINGBUFFER .push (codeBlock .fileName );
138+ var fileHashes : Null <Array <CodeHashes >> = FILE_HASHES .get (codeBlock .fileName );
139+ if (fileHashes == null ) {
140+ fileHashes = [];
141+ FILE_HASHES .set (codeBlock .fileName , fileHashes );
142+ }
143+ fileHashes .push (hashes );
144+ LOCK .release ();
145+ }
146+
147+ static function cleanupRingBuffer (maxFileCount : Int ) {
148+ LOCK .acquire ();
149+ while (FILE_RINGBUFFER .length > maxFileCount ) {
150+ var fileName : String = FILE_RINGBUFFER .shift ();
151+ var fileHashes : Null <Array <CodeHashes >> = FILE_HASHES .get (fileName );
152+ if (fileHashes == null ) {
153+ continue ;
154+ }
155+ for (hash in fileHashes ) {
156+ SIMILAR_HASHES .remove (hash .similarHash );
157+ IDENTICAL_HASHES .remove (hash .identicalHash );
158+ }
159+ FILE_HASHES .remove (fileName );
160+ }
161+ LOCK .release ();
162+ }
163+
164+ static function cleanupFile (fileName : String ) {
165+ LOCK .acquire ();
166+ FILE_RINGBUFFER .remove (fileName );
167+ var fileHashes : Null <Array <CodeHashes >> = FILE_HASHES .get (fileName );
168+ if (fileHashes != null ) {
169+ for (hash in fileHashes ) {
170+ SIMILAR_HASHES .remove (hash .similarHash );
171+ IDENTICAL_HASHES .remove (hash .identicalHash );
172+ }
173+ FILE_HASHES .remove (fileName );
174+ }
175+ LOCK .release ();
176+ }
177+ #end
178+
125179 function makeCodeHashes (token : TokenTree ): CodeHashes {
126180 var similar : StringBuf = new StringBuf ();
127181 var identical : StringBuf = new StringBuf ();
@@ -151,7 +205,10 @@ class CodeSimilarityCheck extends Check {
151205 switch (token .tok ) {
152206 case Const (CFloat (_ )):
153207 return " const_float" ;
154- case Const (CString (_ )):
208+ case Const (CString (s )):
209+ if (StringUtils .isStringInterpolation (s , checker .file .content , token .pos )) {
210+ return " const_string_interpol" ;
211+ }
155212 return " const_string" ;
156213 case Const (CIdent (_ )):
157214 return " identifier" ;
0 commit comments