Package com.jetbrains.lang.dart.analyzer

Source Code of com.jetbrains.lang.dart.analyzer.DartInProcessAnnotator$DartAnnotatorInfo

package com.jetbrains.lang.dart.analyzer;

import com.google.dart.engine.context.AnalysisContext;
import com.google.dart.engine.context.AnalysisException;
import com.google.dart.engine.error.AnalysisError;
import com.google.dart.engine.error.ErrorCode;
import com.google.dart.engine.error.HintCode;
import com.google.dart.engine.error.TodoCode;
import com.intellij.codeInsight.intention.IntentionAction;
import com.intellij.codeInspection.ProblemHighlightType;
import com.intellij.lang.annotation.Annotation;
import com.intellij.lang.annotation.AnnotationHolder;
import com.intellij.lang.annotation.ExternalAnnotator;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleUtilCore;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.xml.XmlFile;
import com.intellij.psi.xml.XmlTag;
import com.intellij.xml.util.HtmlUtil;
import com.jetbrains.lang.dart.psi.DartEmbeddedContent;
import com.jetbrains.lang.dart.psi.DartExpressionCodeFragment;
import com.jetbrains.lang.dart.sdk.DartSdk;
import com.jetbrains.lang.dart.util.DartResolveUtil;
import com.jetbrains.lang.dart.validation.fixes.DartResolverErrorCode;
import com.jetbrains.lang.dart.validation.fixes.DartTypeErrorCode;
import com.jetbrains.lang.dart.validation.fixes.FixAndIntentionAction;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.util.Collections;
import java.util.List;

public class DartInProcessAnnotator extends ExternalAnnotator<DartInProcessAnnotator.DartAnnotatorInfo, AnalysisContext> {
  static final Logger LOG = Logger.getInstance("#com.jetbrains.lang.dart.analyzer.DartInProcessAnnotator");

  public static class DartAnnotatorInfo {
    @NotNull private final AnalysisContext analysisContext;
    @NotNull private final DartFileBasedSource annotatedFile;
    @NotNull private final DartFileBasedSource libraryFile;

    public DartAnnotatorInfo(@NotNull final AnalysisContext analysisContext,
                             @NotNull final DartFileBasedSource annotatedFile,
                             @NotNull final DartFileBasedSource libraryFile) {
      this.analysisContext = analysisContext;
      this.annotatedFile = annotatedFile;
      this.libraryFile = libraryFile;
    }
  }

  @Override
  @Nullable
  public DartAnnotatorInfo collectInformation(@NotNull final PsiFile psiFile) {
    final Project project = psiFile.getProject();

    if (psiFile instanceof DartExpressionCodeFragment) return null;

    final VirtualFile annotatedFile = DartResolveUtil.getRealVirtualFile(psiFile);
    if (annotatedFile == null) return null;

    final Module module = ModuleUtilCore.findModuleForPsiElement(psiFile);
    if (module == null) return null;

    final DartSdk sdk = DartSdk.getGlobalDartSdk();
    if (sdk == null) return null;

    if (psiFile instanceof XmlFile && !containsDartEmbeddedContent((XmlFile)psiFile)) return null;

    if (FileUtil.isAncestor(sdk.getHomePath(), annotatedFile.getPath(), true)) return null;

    final List<VirtualFile> libraries = DartResolveUtil.findLibrary(psiFile, GlobalSearchScope.projectScope(project));
    final VirtualFile libraryFile = libraries.isEmpty() || libraries.contains(annotatedFile) ? annotatedFile : libraries.get(0);

    return new DartAnnotatorInfo(DartAnalyzerService.getInstance(project).getAnalysisContext(annotatedFile, sdk.getHomePath()),
                                 DartFileBasedSource.getSource(project, annotatedFile),
                                 DartFileBasedSource.getSource(project, libraryFile));
  }

  private static boolean containsDartEmbeddedContent(final XmlFile file) {
    final String text = file.getText();
    int i = -1;
    while ((i = text.indexOf("application/dart", i + 1)) != -1) {
      final PsiElement element = file.findElementAt(i);
      final XmlTag tag = element == null ? null : PsiTreeUtil.getParentOfType(element, XmlTag.class);
      if (tag != null && HtmlUtil.isScriptTag(tag) && PsiTreeUtil.getChildOfType(tag, DartEmbeddedContent.class) != null) {
        return true;
      }
    }
    return false;
  }

  @Override
  @Nullable
  public AnalysisContext doAnnotate(final DartAnnotatorInfo annotatorInfo) {
    try {
      if (annotatorInfo.annotatedFile != annotatorInfo.libraryFile) {
        annotatorInfo.analysisContext.computeErrors(annotatorInfo.libraryFile);
      }
      annotatorInfo.analysisContext.computeErrors(annotatorInfo.annotatedFile);
      return annotatorInfo.analysisContext;
    }
    catch (AnalysisException e) {
      LOG.info(e);
    }
    return null;
  }

  @Override
  public void apply(@NotNull final PsiFile psiFile,
                    @Nullable final AnalysisContext analysisContext,
                    @NotNull final AnnotationHolder holder) {
    if (analysisContext == null || !psiFile.isValid()) return;

    final VirtualFile annotatedFile = DartResolveUtil.getRealVirtualFile(psiFile);
    final DartFileBasedSource source = annotatedFile == null ? null : DartFileBasedSource.getSource(psiFile.getProject(), annotatedFile);
    if (source == null) return;

    // analysisContext.getErrors() doesn't perform analysis and returns already calculated errors
    final AnalysisError[] messages = analysisContext.getErrors(source).getErrors();
    if (messages == null || messages.length == 0) return;

    final int fileTextLength = psiFile.getTextLength();

    for (AnalysisError message : messages) {
      if (shouldIgnoreMessageFromDartAnalyzer(message)) continue;

      if (source != message.getSource()) {
        LOG.warn("Unexpected Source: " + message.getSource() + ",\nfile: " + annotatedFile.getPath());
        continue;
      }

      final Annotation annotation = annotate(holder, message, fileTextLength);
      if (annotation != null) {
        registerFixes(psiFile, annotation, message);
      }
    }
  }

  public static boolean shouldIgnoreMessageFromDartAnalyzer(final @NotNull AnalysisError message) {
    if (message.getErrorCode() == TodoCode.TODO) return true; // // already done using IDE engine
    if (message.getErrorCode() == HintCode.DEPRECATED_MEMBER_USE) return true; // already done as DartDeprecatedApiUsageInspection
    return false;
  }

  private static void registerFixes(final PsiFile psiFile, final Annotation annotation, final AnalysisError message) {
    List<? extends IntentionAction> fixes = Collections.emptyList();

    //noinspection EnumSwitchStatementWhichMissesCases
    switch (message.getErrorCode().getType()) {
      case STATIC_WARNING:
        final DartResolverErrorCode resolverErrorCode = DartResolverErrorCode.findError(message.getErrorCode().toString());
        if (resolverErrorCode != null) {
          fixes = resolverErrorCode.getFixes(psiFile, message.getOffset(), message.getMessage());
        }
        break;
      case STATIC_TYPE_WARNING:
      case COMPILE_TIME_ERROR:
        final DartTypeErrorCode typeErrorCode = DartTypeErrorCode.findError(message.getErrorCode().toString());
        if (typeErrorCode != null) {
          fixes = typeErrorCode.getFixes(psiFile, message.getOffset(), message.getMessage());
        }
        break;
    }


    if (!fixes.isEmpty()) {
      PsiElement element = psiFile.findElementAt(message.getOffset() + message.getLength() / 2);
      while (element != null && ((annotation.getStartOffset() < element.getTextOffset()) ||
                                 annotation.getEndOffset() > element.getTextRange().getEndOffset())) {
        element = element.getParent();
      }

      if (element != null && (annotation.getStartOffset() != element.getTextRange().getStartOffset() ||
                              annotation.getEndOffset() != element.getTextRange().getEndOffset())) {
        element = null;
      }

      for (IntentionAction intentionAction : fixes) {
        if (intentionAction instanceof FixAndIntentionAction) {
          ((FixAndIntentionAction)intentionAction).setElement(element);
        }
        annotation.registerFix(intentionAction);
      }
    }
  }

  @Nullable
  private static Annotation annotate(final AnnotationHolder holder, final AnalysisError message, final int fileTextLength) {
    int highlightingStart = message.getOffset();
    int highlightingEnd = message.getOffset() + message.getLength();
    if (highlightingEnd > fileTextLength) highlightingEnd = fileTextLength;
    if (highlightingStart >= highlightingEnd) highlightingStart = highlightingEnd - 1;

    final TextRange textRange = new TextRange(highlightingStart, highlightingEnd);
    final ErrorCode errorCode = message.getErrorCode();

    switch (errorCode.getErrorSeverity()) {
      case NONE:
        return null;
      case INFO:
        final Annotation annotation = holder.createWeakWarningAnnotation(textRange, message.getMessage());
        if (errorCode == HintCode.UNUSED_IMPORT || errorCode == HintCode.DUPLICATE_IMPORT) {
          annotation.setHighlightType(ProblemHighlightType.LIKE_UNUSED_SYMBOL);
        }
        return annotation;
      case WARNING:
        return holder.createWarningAnnotation(textRange, message.getMessage());
      case ERROR:
        return holder.createErrorAnnotation(textRange, message.getMessage());
    }
    return null;
  }
}
TOP

Related Classes of com.jetbrains.lang.dart.analyzer.DartInProcessAnnotator$DartAnnotatorInfo

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.