in flutter-idea/src/io/flutter/editor/FlutterIconLineMarkerProvider.java [92:227]
LineMarkerInfo<?> getLineMarkerInfo(@NotNull PsiElement element, @NotNull FlutterSdk sdk) {
if ((element.getNode() != null ? element.getNode().getElementType() : null) != DartTokenTypes.IDENTIFIER) return null;
final String name = element.getText();
assert name != null;
if (!KnownPaths.containsKey(name)) return null;
final PsiElement refExpr = topmostReferenceExpression(element);
if (refExpr == null) return null;
PsiElement parent = refExpr.getParent();
if (parent == null) return null;
String knownPath = null;
assert ApplicationManager.getApplication() != null;
if (!ApplicationManager.getApplication().isUnitTestMode()) {
// Resolve the class reference and check that it is one of the known, cached classes.
final PsiElement symbol = "IconData".equals(name) ? refExpr : refExpr.getFirstChild();
if (!(symbol instanceof DartReference)) return null;
final PsiElement result = ((DartReference)symbol).resolve();
if (result == null) return null;
assert result.getContainingFile() != null;
final List<VirtualFile> library = DartResolveUtil.findLibrary(result.getContainingFile());
for (VirtualFile file : library) {
assert file != null;
final VirtualFile dir = file.getParent();
assert dir != null;
if (dir.isInLocalFileSystem()) {
final String path = dir.getPath();
String trimmedPath = path;
if (!path.endsWith("lib")) {
final int index = path.indexOf("lib");
if (index >= 0) {
trimmedPath = path.substring(0, index + 3);
}
}
final Set<String> knownPaths = KnownPaths.get(name);
assert knownPaths != null; // Due to guard clause above.
if (knownPaths.contains(path) || knownPaths.contains(trimmedPath)) {
knownPath = file.getPath();
break;
}
for (String aPath : knownPaths) {
assert aPath != null;
if (path.endsWith(aPath) || aPath.contains(path) || trimmedPath.endsWith(aPath) || aPath.contains(trimmedPath)) {
knownPath = file.getPath();
break;
}
}
}
}
if (knownPath == null) return null;
}
final ASTNode parentNode = parent.getNode();
assert parentNode != null;
if (parentNode.getElementType() == DartTokenTypes.CALL_EXPRESSION) {
// Check font family and package
final DartArguments arguments = DartPsiImplUtil.getArguments((DartCallExpression)parent);
if (arguments == null) return null;
final String family = getValueOfNamedArgument(arguments, "fontFamily");
final PsiElement fontPackage = getNamedArgumentExpression(arguments, "fontPackage");
final String argument = getValueOfPositionalArgument(arguments, 0);
if (argument == null) return null;
final Icon icon = getIconFromPackage(fontPackage, family, argument, element.getProject(), sdk);
if (icon != null) {
return createLineMarker(element, icon);
}
}
else if (parentNode.getElementType() == DartTokenTypes.SIMPLE_TYPE) {
parent = getNewExprFromType(parent);
if (parent == null) return null;
final DartArguments arguments = DartPsiImplUtil.getArguments((DartNewExpression)parent);
if (arguments == null) return null;
final String family = getValueOfNamedArgument(arguments, "fontFamily");
final PsiElement fontPackage = getNamedArgumentExpression(arguments, "fontPackage");
final String argument = getValueOfPositionalArgument(arguments, 0);
if (argument == null) return null;
final Icon icon = getIconFromPackage(fontPackage, family, argument, element.getProject(), sdk);
if (icon != null) {
return createLineMarker(element, icon);
}
}
else {
final PsiElement idNode = refExpr.getFirstChild();
if (idNode == null) return null;
if (name.equals(idNode.getText())) {
final PsiElement selectorNode = refExpr.getLastChild();
if (selectorNode == null) return null;
assert selectorNode.getNode() != null;
final String selector = AstBufferUtil.getTextSkippingWhitespaceComments(selectorNode.getNode());
final Icon icon;
if (name.equals("Icons")) {
final IconInfo iconDef = findStandardDefinition(name, selector, element.getProject(), knownPath, sdk);
if (iconDef == null) return null;
// <flutter-sdk>/bin/cache/artifacts/material_fonts/MaterialIcons-Regular.otf
icon = findStandardIconFromDef(name, iconDef, sdk.getHomePath() + MaterialRelativeAssetPath);
}
else if (name.equals("CupertinoIcons")) {
final IconInfo iconDef = findStandardDefinition(name, selector, element.getProject(), knownPath, sdk);
if (iconDef == null) return null;
final String path = FlutterSdkUtil.getPathToCupertinoIconsPackage(element.getProject());
// <pub_cache>/hosted/pub.dartlang.org/cupertino_icons-v.m.n/assets/CupertinoIcons.ttf
icon = findStandardIconFromDef(name, iconDef, path + CupertinoRelativeAssetPath);
}
else {
// Note: I want to keep this code until I'm sure we won't use pubspec.yaml.
//final DartComponent result = DartResolveUtil.findReferenceAndComponentTarget(idNode);
//if (result != null) {
// final VirtualFile map = IconPreviewGenerator.findAssetMapFor(result);
// if (map == null) {
// return null;
// }
// final FileViewProvider provider = PsiManager.getInstance(result.getProject()).findViewProvider(map);
// if (provider != null) {
// final PsiFile psi = provider.getPsi(YAMLLanguage.INSTANCE);
// final YamlAssetMapVisitor visitor = new YamlAssetMapVisitor();
// psi.accept(visitor);
// final HashMap<String, String> assetMap = visitor.assetMap;
// }
//}
final PsiElement iconElement = refExpr.getLastChild();
if (iconElement == null) return null; // TODO check for instance creation with codepoint
final String iconName = iconElement.getText();
assert iconName != null;
assert knownPath != null;
final IconInfo iconDef = findDefinition(name, iconName, element.getProject(), knownPath);
if (iconDef == null) return null;
icon = findIconFromDef(name, iconDef, knownPath);
}
if (icon != null) {
return createLineMarker(element, icon);
}
}
}
return null;
}