43
43
import com .jetbrains .lang .dart .psi .DartVarInit ;
44
44
import com .jetbrains .lang .dart .util .DartPsiImplUtil ;
45
45
import com .jetbrains .lang .dart .util .DartResolveUtil ;
46
+ import gnu .trove .THashSet ;
47
+ import info .debatty .java .stringsimilarity .JaroWinkler ;
46
48
import io .flutter .FlutterBundle ;
47
49
import io .flutter .utils .IconPreviewGenerator ;
48
- import java .util .ArrayList ;
49
- import java .util .HashMap ;
50
- import java .util .List ;
51
- import java .util .Map ;
50
+
51
+ import java .util .*;
52
52
import javax .swing .Icon ;
53
53
import org .jetbrains .annotations .NotNull ;
54
54
import org .jetbrains .annotations .Nullable ;
58
58
59
59
public class FlutterIconLineMarkerProvider extends LineMarkerProviderDescriptor {
60
60
61
- public static final Map <String , String > KnownPaths = new HashMap <>();
61
+ public static final Map <String , Set < String > > KnownPaths = new HashMap <>();
62
62
private static final Logger LOG = Logger .getInstance (FlutterIconLineMarkerProvider .class );
63
63
64
64
static {
65
- KnownPaths .put ("Icons" , "packages/flutter/lib/src/material" );
66
- KnownPaths .put ("IconData" , "packages/flutter/lib/src/widgets" );
67
- KnownPaths .put ("CupertinoIcons" , "packages/flutter/lib/src/cupertino" );
65
+ KnownPaths .put ("Icons" , new THashSet < String >( Collections . singleton ( "packages/flutter/lib/src/material" )) );
66
+ KnownPaths .put ("IconData" , new THashSet < String >( Collections . singleton ( "packages/flutter/lib/src/widgets" )) );
67
+ KnownPaths .put ("CupertinoIcons" , new THashSet < String >( Collections . singleton ( "packages/flutter/lib/src/cupertino" )) );
68
68
}
69
69
70
70
@ Nullable ("null means disabled" )
@@ -84,6 +84,7 @@ public LineMarkerInfo<?> getLineMarkerInfo(@NotNull PsiElement element) {
84
84
if (refExpr == null ) return null ;
85
85
PsiElement parent = refExpr .getParent ();
86
86
if (parent == null ) return null ;
87
+ String knownPath = null ;
87
88
88
89
// Resolve the class reference and check that it is one of the known, cached classes.
89
90
if (!ApplicationManager .getApplication ().isUnitTestMode ()) {
@@ -92,20 +93,25 @@ public LineMarkerInfo<?> getLineMarkerInfo(@NotNull PsiElement element) {
92
93
final PsiElement result = ((DartReference )symbol ).resolve ();
93
94
if (result == null ) return null ;
94
95
final List <VirtualFile > library = DartResolveUtil .findLibrary (result .getContainingFile ());
95
- boolean found = false ;
96
96
for (VirtualFile file : library ) {
97
- VirtualFile dir = file .getParent ();
97
+ final VirtualFile dir = file .getParent ();
98
98
if (dir .isInLocalFileSystem ()) {
99
99
final String path = dir .getPath ();
100
- final String knownPath = KnownPaths .get (name );
101
- if (path . endsWith ( knownPath ) || knownPath .contains (path )) {
102
- found = true ;
100
+ final Set < String > knownPaths = KnownPaths .get (name );
101
+ if (knownPaths .contains (path )) {
102
+ knownPath = path ;
103
103
break ;
104
104
}
105
+ for (String aPath : knownPaths ) {
106
+ if (path .endsWith (aPath ) || aPath .contains (path )) {
107
+ knownPath = aPath ;
108
+ break ;
109
+ }
110
+ }
105
111
}
106
112
}
107
- if (!found ) return null ;
108
113
}
114
+ if (knownPath == null ) return null ;
109
115
110
116
if (parent .getNode ().getElementType () == DartTokenTypes .CALL_EXPRESSION ) {
111
117
// Check font family and package
@@ -170,9 +176,9 @@ else if (name.equals("CupertinoIcons")) {
170
176
final PsiElement symbol = refExpr .getLastChild ();
171
177
if (symbol == null ) return null ; // TODO check for instance creation with codepoint
172
178
final String iconName = symbol .getText ();
173
- final IconInfo iconDef = findDefinition (name , iconName , element .getProject ());
179
+ final IconInfo iconDef = findDefinition (name , iconName , element .getProject (), knownPath );
174
180
if (iconDef == null ) return null ;
175
- icon = findIconFromDef (name , iconDef );
181
+ icon = findIconFromDef (name , iconDef , knownPath );
176
182
}
177
183
if (icon != null ) {
178
184
return createLineMarker (element , icon );
@@ -201,29 +207,28 @@ private Icon getIconFromCode(@NotNull String value) {
201
207
202
208
private LineMarkerInfo <PsiElement > createLineMarker (@ Nullable PsiElement element , @ NotNull Icon icon ) {
203
209
if (element == null ) return null ;
210
+ //noinspection MissingRecentApi
204
211
return new LineMarkerInfo <>(element , element .getTextRange (), icon , null , null ,
205
212
GutterIconRenderer .Alignment .LEFT , () -> "" );
206
213
}
207
214
208
- private IconInfo findDefinition (@ NotNull String className , @ NotNull String iconName , @ NotNull Project project ) {
209
- final String path = KnownPaths .get (className );
215
+ private IconInfo findDefinition (@ NotNull String className , @ NotNull String iconName , @ NotNull Project project , @ NotNull String path ) {
210
216
final VirtualFile virtualFile = LocalFileSystem .getInstance ().findFileByPath (path );
211
217
if (virtualFile == null ) return null ;
212
218
final PsiFile psiFile = PsiManager .getInstance (project ).findFile (virtualFile );
213
219
if (psiFile == null ) {
214
220
return null ;
215
221
}
216
- IconInfoVisitor visitor = new IconInfoVisitor (iconName );
222
+ final IconInfoVisitor visitor = new IconInfoVisitor (iconName );
217
223
psiFile .accept (visitor );
218
224
return visitor .info ;
219
225
}
220
226
221
- private Icon findIconFromDef (String iconClassName , IconInfo iconDef ) {
222
- final String path = KnownPaths .get (iconClassName );
227
+ private Icon findIconFromDef (@ NotNull String iconClassName , @ NotNull IconInfo iconDef , @ NotNull String path ) {
223
228
final VirtualFile virtualFile = LocalFileSystem .getInstance ().findFileByPath (path );
224
229
if (virtualFile == null ) return null ;
225
230
final VirtualFile parent = virtualFile .getParent ();
226
- List <VirtualFile > ttfFiles = new ArrayList <>();
231
+ final List <VirtualFile > ttfFiles = new ArrayList <>();
227
232
VfsUtilCore .visitChildrenRecursively (parent , new VirtualFileVisitor <Object >() {
228
233
@ Override
229
234
public boolean visitFile (@ NotNull VirtualFile file ) {
@@ -236,33 +241,34 @@ public boolean visitFile(@NotNull VirtualFile file) {
236
241
}
237
242
}
238
243
});
239
- int match = -1 ;
244
+ double match = -1 ;
240
245
String family = iconDef .familyName ;
241
246
VirtualFile bestFileMatch = null ;
242
247
if (family == null ) family = "FontAwesomeSolid" ;
243
248
for (VirtualFile file : ttfFiles ) {
244
- int n = findPattern (file .getNameWithoutExtension (), family );
249
+ final double n = findPattern (file .getNameWithoutExtension (), family );
245
250
if (n > match ) {
246
251
match = n ;
247
252
bestFileMatch = file ;
248
253
}
249
254
}
250
255
if (bestFileMatch != null ) {
251
- IconPreviewGenerator generator = new IconPreviewGenerator (bestFileMatch .getPath ());
252
- Icon icon = generator .convert (iconDef .codepoint );
256
+ final IconPreviewGenerator generator = new IconPreviewGenerator (bestFileMatch .getPath ());
257
+ final Icon icon = generator .convert (iconDef .codepoint );
253
258
if (icon != null ) return icon ;
254
259
}
255
260
for (VirtualFile file : ttfFiles ) {
256
- IconPreviewGenerator generator = new IconPreviewGenerator (file .getPath ());
257
- Icon icon = generator .convert (iconDef .codepoint );
261
+ final IconPreviewGenerator generator = new IconPreviewGenerator (file .getPath ());
262
+ final Icon icon = generator .convert (iconDef .codepoint );
258
263
if (icon != null ) return icon ;
259
264
}
260
265
return null ;
261
266
}
262
267
263
- public int findPattern (String t , String p ) {
268
+ public double findPattern (@ NotNull String t , @ NotNull String p ) {
264
269
// TODO Experiment with https://github.com/tdebatty/java-string-similarity
265
- return 0 ;
270
+ final JaroWinkler jw = new JaroWinkler ();
271
+ return jw .similarity (t , p );
266
272
}
267
273
268
274
static class IconInfo {
@@ -299,7 +305,7 @@ else if (expression instanceof DartStringLiteralExpression) {
299
305
}
300
306
else if (expression .getNode ().getElementType () == DartTokenTypes .REFERENCE_EXPRESSION ) {
301
307
final Pair <String , TextRange > pair = DartPsiImplUtil .getUnquotedDartStringAndItsRange (expression .getText ().trim ());
302
- String varName = pair .first ;
308
+ final String varName = pair .first ;
303
309
return staticVars .get (varName );
304
310
}
305
311
return null ;
@@ -308,11 +314,11 @@ else if (expression.getNode().getElementType() == DartTokenTypes.REFERENCE_EXPRE
308
314
@ Override
309
315
public void visitVarAccessDeclaration (@ NotNull DartVarAccessDeclaration o ) {
310
316
if (o .getComponentName ().getText ().trim ().equals (iconName )) {
311
- DartVarInit init = (DartVarInit )o .getParent ().getLastChild ();
317
+ final DartVarInit init = (DartVarInit )o .getParent ().getLastChild ();
312
318
final DartExpression expression = init .getExpression ();
313
319
if (expression instanceof DartNewExpression ) {
314
- DartNewExpression newExpr = (DartNewExpression )expression ;
315
- DartType type = newExpr .getType ();
320
+ final DartNewExpression newExpr = (DartNewExpression )expression ;
321
+ final DartType type = newExpr .getType ();
316
322
if (type != null ) {
317
323
final String className = type .getText ();
318
324
if (KnownPaths .containsKey (className )) {
@@ -322,9 +328,9 @@ public void visitVarAccessDeclaration(@NotNull DartVarAccessDeclaration o) {
322
328
if (argumentList != null ) {
323
329
final List <DartExpression > list = argumentList .getExpressionList ();
324
330
if (!list .isEmpty ()) {
325
- String codepoint = list .get (0 ).getText ();
326
- final PsiElement family = getNamedArgumentExpression (arguments , "family " );
327
- String familyName = findFamilyName (family , type );
331
+ final String codepoint = list .get (0 ).getText ();
332
+ final PsiElement family = getNamedArgumentExpression (arguments , "fontFamily " );
333
+ final String familyName = findFamilyName (family , type );
328
334
info = new IconInfo (className , iconName , familyName , codepoint );
329
335
}
330
336
}
@@ -335,8 +341,8 @@ public void visitVarAccessDeclaration(@NotNull DartVarAccessDeclaration o) {
335
341
}
336
342
else {
337
343
if (o .getFirstChild ().getText ().trim ().equals ("static" )) {
338
- String varName = o .getComponentName ().getText ().trim ();
339
- DartVarInit init = (DartVarInit )o .getParent ().getLastChild ();
344
+ final String varName = o .getComponentName ().getText ().trim ();
345
+ final DartVarInit init = (DartVarInit )o .getParent ().getLastChild ();
340
346
final DartExpression expression = init .getExpression ();
341
347
if (expression instanceof DartStringLiteralExpression ) {
342
348
final Pair <String , TextRange > pair = DartPsiImplUtil .getUnquotedDartStringAndItsRange (expression .getText ());
0 commit comments