3939import org .sonar .api .batch .fs .InputFile ;
4040import org .sonar .api .batch .sensor .SensorContext ;
4141import org .sonar .api .issue .NoSonarFilter ;
42- import org .sonar .api .measures .CoreMetrics ;
43- import org .sonar .api .measures .FileLinesContext ;
4442import org .sonar .api .measures .FileLinesContextFactory ;
45- import org .sonar .api .measures .Metric ;
4643import org .sonar .plugins .python .api .PythonCheck ;
4744import org .sonar .plugins .python .api .PythonFile ;
4845import org .sonar .plugins .python .api .PythonFileConsumer ;
5451import org .sonar .plugins .python .indexer .PythonIndexer ;
5552import org .sonar .python .IPythonLocation ;
5653import org .sonar .python .SubscriptionVisitor ;
57- import org .sonar .python .metrics .FileLinesVisitor ;
58- import org .sonar .python .metrics .FileMetrics ;
5954import org .sonar .python .parser .PythonParser ;
6055import org .sonar .python .tree .IPythonTreeMaker ;
6156import org .sonar .python .tree .PythonTreeMaker ;
@@ -69,8 +64,6 @@ public class PythonScanner extends Scanner {
6964
7065 private final Supplier <PythonParser > parserSupplier ;
7166 private final PythonChecks checks ;
72- private final FileLinesContextFactory fileLinesContextFactory ;
73- private final NoSonarFilter noSonarFilter ;
7467 private final PythonCpdAnalyzer cpdAnalyzer ;
7568 private final PythonIndexer indexer ;
7669 private final Map <PythonInputFile , Set <Class <? extends PythonCheck >>> checksExecutedWithoutParsingByFiles ;
@@ -81,14 +74,13 @@ public class PythonScanner extends Scanner {
8174 private final NewSymbolsCollector newSymbolsCollector ;
8275 private final PythonHighlighter pythonHighlighter ;
8376 private final IssuesRepository issuesRepository ;
77+ private final MeasuresRepository measuresRepository ;
8478
8579 public PythonScanner (
8680 SensorContext context , PythonChecks checks , FileLinesContextFactory fileLinesContextFactory , NoSonarFilter noSonarFilter ,
8781 Supplier <PythonParser > parserSupplier , PythonIndexer indexer , PythonFileConsumer architectureCallback ) {
8882 super (context );
8983 this .checks = checks ;
90- this .fileLinesContextFactory = fileLinesContextFactory ;
91- this .noSonarFilter = noSonarFilter ;
9284 this .cpdAnalyzer = new PythonCpdAnalyzer (context );
9385 this .parserSupplier = parserSupplier ;
9486 this .indexer = indexer ;
@@ -101,6 +93,7 @@ public PythonScanner(
10193 this .newSymbolsCollector = new NewSymbolsCollector (this );
10294 this .pythonHighlighter = new PythonHighlighter (this );
10395 this .issuesRepository = new IssuesRepository (context , checks , indexer , isInSonarLint (context ), this );
96+ this .measuresRepository = new MeasuresRepository (context , noSonarFilter , fileLinesContextFactory , isInSonarLint (context ), this );
10497 }
10598
10699 @ Override
@@ -150,7 +143,8 @@ private PythonVisitorContext createVisitorContext(PythonInputFile inputFile, Pyt
150143 indexer .cacheContext (),
151144 context .runtime ().getProduct ());
152145 if (fileType == InputFile .Type .MAIN ) {
153- saveMeasures (inputFile , visitorContext );
146+ pushTokens (inputFile , visitorContext );
147+ measuresRepository .save (inputFile , visitorContext );
154148 }
155149 } catch (RecognitionException e ) {
156150 visitorContext = new PythonVisitorContext (pythonFile , e , context .runtime ().getProduct ());
@@ -171,11 +165,18 @@ private PythonVisitorContext createVisitorContext(PythonInputFile inputFile, Pyt
171165 return visitorContext ;
172166 }
173167
174- private void executeChecks (PythonVisitorContext visitorContext , Collection <PythonCheck > checks , InputFile .Type fileType , PythonInputFile inputFile ) {
168+ private synchronized void pushTokens (PythonInputFile inputFile , PythonVisitorContext visitorContext ) {
169+ if (!isInSonarLint (context ) && inputFile .kind () == PythonInputFile .Kind .PYTHON ) {
170+ cpdAnalyzer .pushCpdTokens (inputFile .wrappedFile (), visitorContext );
171+ }
172+ }
173+
174+ private void executeChecks (PythonVisitorContext visitorContext , Collection <PythonCheck > checks , InputFile .Type fileType ,
175+ PythonInputFile inputFile ) {
175176 Collection <PythonSubscriptionCheck > subscriptionChecks = new ArrayList <>();
176177 for (PythonCheck check : checks ) {
177178 if (isCheckNotApplicable (check , fileType )
178- || checksExecutedWithoutParsingByFiles .getOrDefault (inputFile , Collections .emptySet ()).contains (check .getClass ())) {
179+ || checksExecutedWithoutParsingByFiles .getOrDefault (inputFile , Collections .emptySet ()).contains (check .getClass ())) {
179180 continue ;
180181 }
181182 if (check instanceof PythonSubscriptionCheck pythonSubscriptionCheck ) {
@@ -251,7 +252,8 @@ public boolean scanFileWithoutParsing(PythonInputFile inputFile) {
251252 return restoreAndPushMeasuresIfApplicable (inputFile );
252253 }
253254
254- private boolean scanFileWithoutParsingNotSonarPython (PythonInputFile inputFile , PythonCheck check , InputFile .Type fileType , boolean result ,
255+ private boolean scanFileWithoutParsingNotSonarPython (PythonInputFile inputFile , PythonCheck check , InputFile .Type fileType ,
256+ boolean result ,
255257 PythonInputFileContext inputFileContext ) {
256258 if (isCheckNotApplicable (check , fileType )) {
257259 return result ;
@@ -270,7 +272,8 @@ private boolean scanFileWithoutParsingNotSonarPython(PythonInputFile inputFile,
270272 return result ;
271273 }
272274
273- private boolean scanFileWithoutParsingSonarPython (PythonInputFile inputFile , InputFile .Type fileType , PythonInputFileContext inputFileContext , boolean result ) {
275+ private boolean scanFileWithoutParsingSonarPython (PythonInputFile inputFile , InputFile .Type fileType ,
276+ PythonInputFileContext inputFileContext , boolean result ) {
274277 var ourChecks = checks .sonarPythonChecks ();
275278 for (var check : ourChecks ) {
276279 if (isCheckNotApplicable (check , fileType )) {
@@ -332,43 +335,6 @@ protected void reportStatistics(int numSkippedFiles, int numTotalFiles) {
332335 numSkippedFiles , numTotalFiles );
333336 }
334337
335- private synchronized void saveMeasures (PythonInputFile inputFile , PythonVisitorContext visitorContext ) {
336- FileMetrics fileMetrics = new FileMetrics (visitorContext , isNotebook (inputFile ));
337- FileLinesVisitor fileLinesVisitor = fileMetrics .fileLinesVisitor ();
338-
339- noSonarFilter .noSonarInFile (inputFile .wrappedFile (), fileLinesVisitor .getLinesWithNoSonar ());
340-
341- if (!isInSonarLint (context )) {
342- if (inputFile .kind () == PythonInputFile .Kind .PYTHON ) {
343- cpdAnalyzer .pushCpdTokens (inputFile .wrappedFile (), visitorContext );
344- }
345-
346- Set <Integer > linesOfCode = fileLinesVisitor .getLinesOfCode ();
347- saveMetricOnFile (inputFile , CoreMetrics .NCLOC , linesOfCode .size ());
348- saveMetricOnFile (inputFile , CoreMetrics .STATEMENTS , fileMetrics .numberOfStatements ());
349- saveMetricOnFile (inputFile , CoreMetrics .FUNCTIONS , fileMetrics .numberOfFunctions ());
350- saveMetricOnFile (inputFile , CoreMetrics .CLASSES , fileMetrics .numberOfClasses ());
351- saveMetricOnFile (inputFile , CoreMetrics .COMPLEXITY , fileMetrics .complexity ());
352- saveMetricOnFile (inputFile , CoreMetrics .COGNITIVE_COMPLEXITY , fileMetrics .cognitiveComplexity ());
353- saveMetricOnFile (inputFile , CoreMetrics .COMMENT_LINES , fileLinesVisitor .getCommentLineCount ());
354-
355- FileLinesContext fileLinesContext = fileLinesContextFactory .createFor (inputFile .wrappedFile ());
356- if (inputFile .kind () == PythonInputFile .Kind .PYTHON ) {
357- for (int line : linesOfCode ) {
358- fileLinesContext .setIntValue (CoreMetrics .NCLOC_DATA_KEY , line , 1 );
359- }
360- }
361- for (int line : fileLinesVisitor .getExecutableLines ()) {
362- fileLinesContext .setIntValue (CoreMetrics .EXECUTABLE_LINES_DATA_KEY , line , 1 );
363- }
364- fileLinesContext .save ();
365- }
366- }
367-
368- static boolean isNotebook (PythonInputFile inputFile ) {
369- return inputFile .kind () == PythonInputFile .Kind .IPYTHON ;
370- }
371-
372338 private synchronized boolean restoreAndPushMeasuresIfApplicable (PythonInputFile inputFile ) {
373339 if (inputFile .wrappedFile ().type () == InputFile .Type .TEST ) {
374340 return true ;
@@ -377,14 +343,6 @@ private synchronized boolean restoreAndPushMeasuresIfApplicable(PythonInputFile
377343 return cpdAnalyzer .pushCachedCpdTokens (inputFile .wrappedFile (), indexer .cacheContext ());
378344 }
379345
380- private void saveMetricOnFile (PythonInputFile inputFile , Metric <Integer > metric , Integer value ) {
381- context .<Integer >newMeasure ()
382- .withValue (value )
383- .forMetric (metric )
384- .on (inputFile .wrappedFile ())
385- .save ();
386- }
387-
388346 public int getRecognitionErrorCount () {
389347 return recognitionErrorCount .get ();
390348 }
0 commit comments