LineMarkerInfo getLineMarkerInfo()

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;
  }