1+ /*
2+ * Copyright 2021 The Chromium Authors. All rights reserved.
3+ * Use of this source code is governed by a BSD-style license that can be
4+ * found in the LICENSE file.
5+ */
6+ package io .flutter .run .coverage ;
7+
8+ import com .intellij .coverage .CoverageAnnotator ;
9+ import com .intellij .coverage .CoverageEngine ;
10+ import com .intellij .coverage .CoverageFileProvider ;
11+ import com .intellij .coverage .CoverageRunner ;
12+ import com .intellij .coverage .CoverageSuite ;
13+ import com .intellij .coverage .CoverageSuitesBundle ;
14+ import com .intellij .execution .configurations .RunConfigurationBase ;
15+ import com .intellij .execution .configurations .RunProfile ;
16+ import com .intellij .execution .configurations .WrappingRunConfiguration ;
17+ import com .intellij .execution .configurations .coverage .CoverageEnabledConfiguration ;
18+ import com .intellij .execution .testframework .AbstractTestProxy ;
19+ import com .intellij .openapi .module .Module ;
20+ import com .intellij .openapi .project .Project ;
21+ import com .intellij .openapi .vfs .VirtualFile ;
22+ import com .intellij .psi .PsiElement ;
23+ import com .intellij .psi .PsiFile ;
24+ import com .jetbrains .lang .dart .DartFileType ;
25+ import com .jetbrains .lang .dart .psi .DartFile ;
26+ import io .flutter .FlutterBundle ;
27+ import io .flutter .FlutterUtils ;
28+ import io .flutter .pub .PubRoot ;
29+ import io .flutter .run .test .TestConfig ;
30+
31+ import java .io .File ;
32+ import java .util .HashSet ;
33+ import java .util .List ;
34+ import java .util .Set ;
35+
36+ import org .jetbrains .annotations .NotNull ;
37+ import org .jetbrains .annotations .Nullable ;
38+
39+ public class FlutterCoverageEngine extends CoverageEngine {
40+
41+ public static FlutterCoverageEngine getInstance () {
42+ return CoverageEngine .EP_NAME .findExtensionOrFail (FlutterCoverageEngine .class );
43+ }
44+
45+ @ Override
46+ public boolean isApplicableTo (@ NotNull RunConfigurationBase conf ) {
47+ return unwrapRunProfile (conf ) instanceof TestConfig ;
48+ }
49+
50+ @ Override
51+ public boolean canHavePerTestCoverage (@ NotNull RunConfigurationBase conf ) {
52+ return true ;
53+ }
54+
55+ @ Override
56+ public @ NotNull CoverageEnabledConfiguration createCoverageEnabledConfiguration (@ NotNull RunConfigurationBase conf ) {
57+ return new FlutterCoverageEnabledConfiguration (conf );
58+ }
59+
60+ @ Override
61+ public @ Nullable CoverageSuite createCoverageSuite (@ NotNull CoverageRunner covRunner ,
62+ @ NotNull String name ,
63+ @ NotNull CoverageFileProvider coverageDataFileProvider ,
64+ @ Nullable String [] filters ,
65+ long lastCoverageTimeStamp ,
66+ @ Nullable String suiteToMerge ,
67+ boolean coverageByTestEnabled ,
68+ boolean tracingEnabled ,
69+ boolean trackTestFolders ,
70+ Project project ) {
71+ return null ;
72+ }
73+
74+ @ Override
75+ public @ Nullable CoverageSuite createCoverageSuite (@ NotNull CoverageRunner covRunner ,
76+ @ NotNull String name ,
77+ @ NotNull CoverageFileProvider coverageDataFileProvider ,
78+ @ NotNull CoverageEnabledConfiguration config ) {
79+ if (config instanceof FlutterCoverageEnabledConfiguration ) {
80+ return new FlutterCoverageSuite (covRunner , name , coverageDataFileProvider ,
81+ config .getConfiguration ().getProject (), this );
82+ }
83+ return null ;
84+ }
85+
86+ @ Override
87+ public @ Nullable CoverageSuite createEmptyCoverageSuite (@ NotNull CoverageRunner coverageRunner ) {
88+ return new FlutterCoverageSuite (this );
89+ }
90+
91+ @ Override
92+ public @ NotNull CoverageAnnotator getCoverageAnnotator (Project project ) {
93+ return FlutterCoverageAnnotator .getInstance (project );
94+ }
95+
96+ @ Override
97+ public boolean coverageEditorHighlightingApplicableTo (@ NotNull PsiFile psiFile ) {
98+ final PubRoot root = PubRoot .forPsiFile (psiFile );
99+ if (root == null ) return false ;
100+ final VirtualFile file = psiFile .getVirtualFile ();
101+ if (file == null ) return false ;
102+ final String path = root .getRelativePath (file );
103+ if (path == null ) return false ;
104+ return path .startsWith ("lib" ) && FlutterUtils .isDartFile (file );
105+ }
106+
107+ @ Override
108+ public boolean coverageProjectViewStatisticsApplicableTo (VirtualFile fileOrDir ) {
109+ return !fileOrDir .isDirectory () && fileOrDir .getFileType () instanceof DartFileType ;
110+ }
111+
112+ @ Override
113+ public boolean acceptedByFilters (@ NotNull PsiFile psiFile , @ NotNull CoverageSuitesBundle suite ) {
114+ return psiFile instanceof DartFile ;
115+ }
116+
117+ @ Override
118+ public boolean recompileProjectAndRerunAction (@ NotNull Module module ,
119+ @ NotNull CoverageSuitesBundle suite ,
120+ @ NotNull Runnable chooseSuiteAction ) {
121+ return false ;
122+ }
123+
124+ @ Override
125+ public String getQualifiedName (@ NotNull final File outputFile ,
126+ @ NotNull final PsiFile sourceFile ) {
127+ return getQName (sourceFile );
128+ }
129+
130+ @ Override
131+ public @ NotNull Set <String > getQualifiedNames (@ NotNull PsiFile sourceFile ) {
132+ final Set <String > qualifiedNames = new HashSet <>();
133+ qualifiedNames .add (getQName (sourceFile ));
134+ return qualifiedNames ;
135+ }
136+
137+ @ Override
138+ public List <PsiElement > findTestsByNames (@ NotNull String [] testNames , @ NotNull Project project ) {
139+ return null ;
140+ }
141+
142+ @ Override
143+ public @ Nullable String getTestMethodName (@ NotNull PsiElement element , @ NotNull AbstractTestProxy testProxy ) {
144+ return null ;
145+ }
146+
147+ @ Override
148+ public String getPresentableText () {
149+ return FlutterBundle .message ("flutter.coverage.presentable.text" );
150+ }
151+
152+ @ NotNull
153+ private static String getQName (@ NotNull PsiFile sourceFile ) {
154+ return sourceFile .getVirtualFile ().getPath ();
155+ }
156+
157+ static @ NotNull RunProfile unwrapRunProfile (@ NotNull RunProfile runProfile ) {
158+ if (runProfile instanceof WrappingRunConfiguration ) {
159+ return ((WrappingRunConfiguration <?>)runProfile ).getPeer ();
160+ }
161+ return runProfile ;
162+ }
163+ }
0 commit comments