@Override
  public void annotateExternally(
      @NotNull final PsiModifierListOwner listOwner,
      @NotNull final String annotationFQName,
      @NotNull final PsiFile fromFile,
      final PsiNameValuePair[] value) {
    final Project project = myPsiManager.getProject();
    final PsiFile containingFile = listOwner.getContainingFile();
    if (!(containingFile instanceof PsiJavaFile)) {
      return;
    }
    final String packageName = ((PsiJavaFile) containingFile).getPackageName();
    final VirtualFile virtualFile = containingFile.getVirtualFile();
    LOG.assertTrue(virtualFile != null);
    final List<OrderEntry> entries =
        ProjectRootManager.getInstance(project).getFileIndex().getOrderEntriesForFile(virtualFile);
    if (entries.isEmpty()) {
      return;
    }
    for (final OrderEntry entry : entries) {
      if (entry instanceof ModuleOrderEntry) continue;
      VirtualFile[] virtualFiles = AnnotationOrderRootType.getFiles(entry);
      virtualFiles = filterByReadOnliness(virtualFiles);

      if (virtualFiles.length > 0) {
        chooseRootAndAnnotateExternally(
            listOwner,
            annotationFQName,
            fromFile,
            project,
            packageName,
            virtualFile,
            virtualFiles,
            value);
      } else {
        if (ApplicationManager.getApplication().isUnitTestMode()
            || ApplicationManager.getApplication().isHeadlessEnvironment()) {
          return;
        }
        SwingUtilities.invokeLater(
            new Runnable() {
              @Override
              public void run() {
                setupRootAndAnnotateExternally(
                    entry,
                    project,
                    listOwner,
                    annotationFQName,
                    fromFile,
                    packageName,
                    virtualFile,
                    value);
              }
            });
      }
      break;
    }
  }
예제 #2
0
 static boolean isAnnotationEditable(@NotNull PsiElement element) {
   PsiModifierListOwner annotationOwner = getAnnotationOwner(element);
   PsiAnnotation annotation = findKotlinSignatureAnnotation(element);
   assert annotation != null;
   if (annotation.getContainingFile() == annotationOwner.getContainingFile()) {
     return annotation.isWritable();
   } else {
     ExternalAnnotationsManager annotationsManager =
         ExternalAnnotationsManager.getInstance(element.getProject());
     return annotationsManager.isExternalAnnotationWritable(
         annotationOwner, KOTLIN_SIGNATURE_ANNOTATION);
   }
 }
예제 #3
0
  @Override
  public void invoke(
      @NotNull Project project,
      @NotNull PsiFile file,
      @Nullable("is null when called from inspection") Editor editor,
      @NotNull PsiElement startElement,
      @NotNull PsiElement endElement) {
    final PsiModifierListOwner myModifierListOwner = (PsiModifierListOwner) startElement;

    final ExternalAnnotationsManager annotationsManager =
        ExternalAnnotationsManager.getInstance(project);
    final PsiModifierList modifierList = myModifierListOwner.getModifierList();
    LOG.assertTrue(modifierList != null);
    if (modifierList.findAnnotation(myAnnotation) != null) return;
    final ExternalAnnotationsManager.AnnotationPlace annotationAnnotationPlace =
        annotationsManager.chooseAnnotationsPlace(myModifierListOwner);
    if (annotationAnnotationPlace == ExternalAnnotationsManager.AnnotationPlace.NOWHERE) return;
    if (annotationAnnotationPlace == ExternalAnnotationsManager.AnnotationPlace.EXTERNAL) {
      for (String fqn : myAnnotationsToRemove) {
        annotationsManager.deannotate(myModifierListOwner, fqn);
      }
      annotationsManager.annotateExternally(myModifierListOwner, myAnnotation, file, myPairs);
    } else {
      final PsiFile containingFile = myModifierListOwner.getContainingFile();
      if (!CodeInsightUtilBase.preparePsiElementForWrite(containingFile)) return;
      for (String fqn : myAnnotationsToRemove) {
        PsiAnnotation annotation = AnnotationUtil.findAnnotation(myModifierListOwner, fqn);
        if (annotation != null) {
          annotation.delete();
        }
      }

      PsiAnnotation inserted = modifierList.addAnnotation(myAnnotation);
      for (PsiNameValuePair pair : myPairs) {
        inserted.setDeclaredAttributeValue(pair.getName(), pair.getValue());
      }
      JavaCodeStyleManager.getInstance(project).shortenClassReferences(inserted);
      if (containingFile != file) {
        UndoUtil.markPsiFileForUndo(file);
      }
    }
  }
  @Override
  @Nullable
  public List<PsiFile> findExternalAnnotationsFiles(@NotNull PsiModifierListOwner listOwner) {
    final PsiFile containingFile = listOwner.getContainingFile();
    if (!(containingFile instanceof PsiJavaFile)) {
      return null;
    }
    final PsiJavaFile javaFile = (PsiJavaFile) containingFile;
    final String packageName = javaFile.getPackageName();
    final VirtualFile virtualFile = containingFile.getVirtualFile();
    if (virtualFile == null) return null;

    final List<PsiFile> files = myExternalAnnotations.get(virtualFile);
    if (files == NULL_LIST) return null;
    if (files != null) {
      boolean allValid = true;
      for (PsiFile file : files) {
        allValid &= file.isValid();
      }
      if (allValid) {
        return files;
      }
    }

    if (virtualFile == null) {
      return null;
    }

    Set<PsiFile> possibleAnnotationsXmls = new THashSet<PsiFile>();
    for (VirtualFile root : getExternalAnnotationsRoots(virtualFile)) {
      final VirtualFile ext =
          root.findFileByRelativePath(packageName.replace('.', '/') + "/" + ANNOTATIONS_XML);
      if (ext == null) continue;
      final PsiFile psiFile = myPsiManager.findFile(ext);
      if (psiFile == null) continue;
      possibleAnnotationsXmls.add(psiFile);
    }
    List<PsiFile> result;
    if (possibleAnnotationsXmls.isEmpty()) {
      myExternalAnnotations.put(virtualFile, NULL_LIST);
      result = null;
    } else {
      result = new SmartList<PsiFile>(possibleAnnotationsXmls);
      // sorting by writability: writable go first
      Collections.sort(
          result,
          new Comparator<PsiFile>() {
            @Override
            public int compare(PsiFile f1, PsiFile f2) {
              boolean w1 = f1.isWritable();
              boolean w2 = f2.isWritable();
              if (w1 == w2) {
                return 0;
              }
              return w1 ? -1 : 1;
            }
          });

      myExternalAnnotations.put(virtualFile, result);
    }
    return result;
  }