public static void enumerate(
      @NotNull PsiElement host,
      @NotNull PsiFile containingFile,
      boolean probeUp,
      @NotNull PsiLanguageInjectionHost.InjectedPsiVisitor visitor) {
    // do not inject into nonphysical files except during completion
    if (!containingFile.isPhysical() && containingFile.getOriginalFile() == containingFile) {
      final PsiElement context =
          InjectedLanguageManager.getInstance(containingFile.getProject())
              .getInjectionHost(containingFile);
      if (context == null) return;

      final PsiFile file = context.getContainingFile();
      if (file == null || !file.isPhysical() && file.getOriginalFile() == file) return;
    }

    if (containingFile.getViewProvider() instanceof InjectedFileViewProvider)
      return; // no injection inside injection

    PsiElement inTree = loadTree(host, containingFile);
    if (inTree != host) {
      host = inTree;
      containingFile = host.getContainingFile();
    }

    MultiHostRegistrarImpl registrar = probeElementsUp(host, containingFile, probeUp);
    if (registrar == null) {
      return;
    }
    List<Pair<Place, PsiFile>> places = registrar.getResult();
    for (Pair<Place, PsiFile> pair : places) {
      PsiFile injectedPsi = pair.second;
      visitor.visit(injectedPsi, pair.first);
    }
  }
  @Nullable
  public ProblemDescriptor[] checkFile(
      @NotNull PsiFile file, @NotNull InspectionManager manager, boolean isOnTheFly) {
    if (InjectedLanguageManager.getInstance(file.getProject()).isInjectedFragment(file))
      return null;
    if (ArrayUtil.find(file.getPsiRoots(), file) != 0) return null;
    if (!file.isPhysical()) return null;
    VirtualFile virtualFile = file.getVirtualFile();
    if (virtualFile == null) return null;
    if (virtualFile.getFileSystem() != LocalFileSystem.getInstance()
        // tests
        && virtualFile.getFileSystem() != TempFileSystem.getInstance()) return null;
    String text = file.getText();
    Charset charset =
        LoadTextUtil.extractCharsetFromFileContent(file.getProject(), virtualFile, text);

    // no sense in checking transparently decoded file: all characters there are already safely
    // encoded
    if (charset instanceof Native2AsciiCharset) return null;

    List<ProblemDescriptor> descriptors = new SmartList<ProblemDescriptor>();
    checkIfCharactersWillBeLostAfterSave(file, manager, isOnTheFly, text, charset, descriptors);
    checkFileLoadedInWrongEncoding(file, manager, isOnTheFly, virtualFile, charset, descriptors);

    return descriptors.toArray(new ProblemDescriptor[descriptors.size()]);
  }
  @NotNull
  private static Document setupFileEditorAndDocument(
      @NotNull String fileName, @NotNull String fileText) throws IOException {
    EncodingProjectManager.getInstance(getProject()).setEncoding(null, CharsetToolkit.UTF8_CHARSET);
    EncodingProjectManager.getInstance(ProjectManager.getInstance().getDefaultProject())
        .setEncoding(null, CharsetToolkit.UTF8_CHARSET);
    PostprocessReformattingAspect.getInstance(ourProject).doPostponedFormatting();
    deleteVFile();
    myVFile = getSourceRoot().createChildData(null, fileName);
    VfsUtil.saveText(myVFile, fileText);
    final FileDocumentManager manager = FileDocumentManager.getInstance();
    final Document document = manager.getDocument(myVFile);
    assertNotNull("Can't create document for '" + fileName + "'", document);
    manager.reloadFromDisk(document);
    document.insertString(0, " ");
    document.deleteString(0, 1);
    myFile = getPsiManager().findFile(myVFile);
    assertNotNull(
        "Can't create PsiFile for '" + fileName + "'. Unknown file type most probably.", myFile);
    assertTrue(myFile.isPhysical());
    myEditor = createEditor(myVFile);
    myVFile.setCharset(CharsetToolkit.UTF8_CHARSET);

    PsiDocumentManager.getInstance(getProject()).commitAllDocuments();
    return document;
  }
  @Override
  public boolean isInProject(@NotNull PsiElement element) {
    PsiFile file = element.getContainingFile();
    if (file != null
        && file.isPhysical()
        && file.getViewProvider().getVirtualFile() instanceof LightVirtualFile) return true;

    if (element instanceof PsiDirectoryContainer) {
      PsiDirectory[] dirs = ((PsiDirectoryContainer) element).getDirectories();
      for (PsiDirectory dir : dirs) {
        if (!isInProject(dir)) return false;
      }
      return true;
    }

    VirtualFile virtualFile = null;
    if (file != null) {
      virtualFile = file.getViewProvider().getVirtualFile();
    } else if (element instanceof PsiFileSystemItem) {
      virtualFile = ((PsiFileSystemItem) element).getVirtualFile();
    }

    if (virtualFile != null) {
      return myExcludedFileIndex.isInContent(virtualFile);
    }
    return false;
  }
    public void editorCreated(@NotNull EditorFactoryEvent event) {
      synchronized (myLock) {
        if (myIsProjectClosing) return;
      }

      final Editor editor = event.getEditor();
      if (editor.getProject() != myProject) return;
      final PsiFile psiFile =
          ApplicationManager.getApplication()
              .runReadAction(
                  new Computable<PsiFile>() {
                    @Nullable
                    @Override
                    public PsiFile compute() {
                      if (myProject.isDisposed()) return null;
                      final PsiDocumentManager documentManager =
                          PsiDocumentManager.getInstance(myProject);
                      final Document document = editor.getDocument();
                      return documentManager.getPsiFile(document);
                    }
                  });

      if (psiFile != null && myCurrentSuitesBundle != null && psiFile.isPhysical()) {
        final CoverageEngine engine = myCurrentSuitesBundle.getCoverageEngine();
        if (!engine.coverageEditorHighlightingApplicableTo(psiFile)) {
          return;
        }

        SrcFileAnnotator annotator = getAnnotator(editor);
        if (annotator == null) {
          annotator = new SrcFileAnnotator(psiFile, editor);
        }

        final SrcFileAnnotator finalAnnotator = annotator;

        synchronized (ANNOTATORS_LOCK) {
          myAnnotators.put(editor, finalAnnotator);
        }

        final Runnable request =
            new Runnable() {
              @Override
              public void run() {
                if (myProject.isDisposed()) return;
                if (myCurrentSuitesBundle != null) {
                  if (engine.acceptedByFilters(psiFile, myCurrentSuitesBundle)) {
                    finalAnnotator.showCoverageInformation(myCurrentSuitesBundle);
                  }
                }
              }
            };
        myCurrentEditors.put(editor, request);
        myAlarm.addRequest(request, 100);
      }
    }
  public boolean isHighlightingAvailable(PsiFile file) {
    if (myDisabledHighlightingFiles.contains(file)) return false;

    if (file == null || !file.isPhysical()) return false;
    if (file instanceof PsiCompiledElement) return false;
    final FileType fileType = file.getFileType();
    if (fileType == StdFileTypes.GUI_DESIGNER_FORM) {
      return true;
    }
    // To enable T.O.D.O. highlighting
    return !fileType.isBinary();
  }
  private static PsiFile createFileCopy(PsiFile file, long caret, long selEnd) {
    final VirtualFile virtualFile = file.getVirtualFile();
    boolean mayCacheCopy =
        file.isPhysical()
            &&
            // we don't want to cache code fragment copies even if they appear to be physical
            virtualFile != null
            && virtualFile.isInLocalFileSystem();
    long combinedOffsets = caret + (selEnd << 32);
    if (mayCacheCopy) {
      final Trinity<PsiFile, Document, Long> cached =
          SoftReference.dereference(file.getUserData(FILE_COPY_KEY));
      if (cached != null
          && cached.first.getClass().equals(file.getClass())
          && isCopyUpToDate(cached.second, cached.first)) {
        final PsiFile copy = cached.first;
        if (copy.getViewProvider().getModificationStamp()
                > file.getViewProvider().getModificationStamp()
            && cached.third.longValue() != combinedOffsets) {
          // the copy PSI might have some caches that are not cleared on its modification because
          // there are no events in the copy
          //   so, clear all the caches
          // hopefully it's a rare situation that the user invokes completion in different parts of
          // the file
          //   without modifying anything physical in between
          ((PsiModificationTrackerImpl) file.getManager().getModificationTracker()).incCounter();
        }
        final Document document = cached.second;
        assert document != null;
        file.putUserData(
            FILE_COPY_KEY,
            new SoftReference<Trinity<PsiFile, Document, Long>>(
                Trinity.create(copy, document, combinedOffsets)));

        Document originalDocument = file.getViewProvider().getDocument();
        assert originalDocument != null;
        assert originalDocument.getTextLength() == file.getTextLength() : originalDocument;
        document.setText(originalDocument.getImmutableCharSequence());
        return copy;
      }
    }

    final PsiFile copy = (PsiFile) file.copy();
    if (mayCacheCopy) {
      final Document document = copy.getViewProvider().getDocument();
      assert document != null;
      file.putUserData(
          FILE_COPY_KEY,
          new SoftReference<Trinity<PsiFile, Document, Long>>(
              Trinity.create(copy, document, combinedOffsets)));
    }
    return copy;
  }
  private void applyInformationToEditor(FileEditor[] editors, final VirtualFile file) {
    final PsiFile psiFile =
        doInReadActionIfProjectOpen(
            new Computable<PsiFile>() {
              @Nullable
              @Override
              public PsiFile compute() {
                return PsiManager.getInstance(myProject).findFile(file);
              }
            });
    if (psiFile != null && myCurrentSuitesBundle != null && psiFile.isPhysical()) {
      final CoverageEngine engine = myCurrentSuitesBundle.getCoverageEngine();
      if (!engine.coverageEditorHighlightingApplicableTo(psiFile)) {
        return;
      }

      for (FileEditor editor : editors) {
        if (editor instanceof TextEditor) {
          final Editor textEditor = ((TextEditor) editor).getEditor();
          SrcFileAnnotator annotator;
          synchronized (ANNOTATORS_LOCK) {
            annotator = myAnnotators.remove(textEditor);
          }
          if (annotator != null) {
            Disposer.dispose(annotator);
          }
          break;
        }
      }

      for (FileEditor editor : editors) {
        if (editor instanceof TextEditor) {
          final Editor textEditor = ((TextEditor) editor).getEditor();
          SrcFileAnnotator annotator = getAnnotator(textEditor);
          if (annotator == null) {
            annotator = new SrcFileAnnotator(psiFile, textEditor);
            synchronized (ANNOTATORS_LOCK) {
              myAnnotators.put(textEditor, annotator);
            }
          }

          if (myCurrentSuitesBundle != null
              && engine.acceptedByFilters(psiFile, myCurrentSuitesBundle)) {
            annotator.showCoverageInformation(myCurrentSuitesBundle);
          }
        }
      }
    }
  }
Exemple #9
0
 @Nullable
 private static String getQuickNavigateInfo(PsiElement element) {
   final String name =
       ElementDescriptionUtil.getElementDescription(element, UsageViewShortNameLocation.INSTANCE);
   if (StringUtil.isEmpty(name)) return null;
   final String typeName =
       ElementDescriptionUtil.getElementDescription(element, UsageViewTypeLocation.INSTANCE);
   final PsiFile file = element.getContainingFile();
   final StringBuilder sb = new StringBuilder();
   if (StringUtil.isNotEmpty(typeName)) sb.append(typeName).append(" ");
   sb.append("\"").append(name).append("\"");
   if (file != null && file.isPhysical()) {
     sb.append(" [").append(file.getName()).append("]");
   }
   return sb.toString();
 }
 @NotNull
 public <T extends PsiPolyVariantReference> ResolveResult[] resolveWithCaching(
     @NotNull T ref,
     @NotNull PolyVariantResolver<T> resolver,
     boolean needToPreventRecursion,
     boolean incompleteCode,
     @NotNull PsiFile containingFile) {
   ResolveResult[] result =
       resolve(
           ref,
           resolver,
           needToPreventRecursion,
           incompleteCode,
           true,
           containingFile.isPhysical());
   return result == null ? ResolveResult.EMPTY_ARRAY : result;
 }
 public static void sendAfterChildrenChangedEvent(
     @NotNull PsiManagerImpl manager,
     @NotNull PsiFile scope,
     int oldLength,
     boolean isGenericChange) {
   if (!scope.isPhysical()) {
     manager.afterChange(false);
     return;
   }
   PsiTreeChangeEventImpl event = new PsiTreeChangeEventImpl(manager);
   event.setParent(scope);
   event.setFile(scope);
   event.setOffset(0);
   event.setOldLength(oldLength);
   event.setGenericChange(isGenericChange);
   manager.childrenChanged(event);
 }
  @NotNull
  public <T extends PsiPolyVariantReference> ResolveResult[] resolveWithCaching(
      @NotNull final T ref,
      @NotNull final PolyVariantContextResolver<T> resolver,
      boolean needToPreventRecursion,
      final boolean incompleteCode,
      @NotNull final PsiFile containingFile) {
    ProgressIndicatorProvider.checkCanceled();
    ApplicationManager.getApplication().assertReadAccessAllowed();

    int index = getIndex(containingFile.isPhysical(), incompleteCode, true);
    ConcurrentMap<T, ResolveResult[]> map = getMap(index);
    ResolveResult[] result = map.get(ref);
    if (result != null) {
      return result;
    }

    RecursionGuard.StackStamp stamp = myGuard.markStack();
    result =
        needToPreventRecursion
            ? myGuard.doPreventingRecursion(
                Pair.create(ref, incompleteCode),
                true,
                new Computable<ResolveResult[]>() {
                  @Override
                  public ResolveResult[] compute() {
                    return resolver.resolve(ref, containingFile, incompleteCode);
                  }
                })
            : resolver.resolve(ref, containingFile, incompleteCode);

    if (stamp.mayCacheNow()) {
      cache(ref, map, result);
    }
    return result == null ? ResolveResult.EMPTY_ARRAY : result;
  }
 @Override
 public void visitFile(PsiFile file) {
   super.visitFile(file);
   if (InjectedLanguageManager.getInstance(file.getProject()).isInjectedFragment(file)
       || !file.isPhysical()) {
     return;
   }
   final VirtualFile virtualFile = file.getVirtualFile();
   final String text = file.getText();
   final Charset charset =
       LoadTextUtil.extractCharsetFromFileContent(file.getProject(), virtualFile, text);
   final CharsetEncoder encoder =
       charset.newEncoder().onUnmappableCharacter(CodingErrorAction.REPORT);
   final CharBuffer charBuffer = CharBuffer.allocate(1);
   final ByteBuffer byteBuffer = ByteBuffer.allocate(10);
   final int length = text.length();
   for (int i = 0; i < length; i++) {
     final char c = text.charAt(i);
     if (c != '\\') {
       continue;
     }
     boolean isEscape = true;
     int previousChar = i - 1;
     while (previousChar >= 0 && text.charAt(previousChar) == '\\') {
       isEscape = !isEscape;
       previousChar--;
     }
     if (!isEscape) {
       continue;
     }
     int nextChar = i;
     do {
       nextChar++;
       if (nextChar >= length) {
         break;
       }
     } while (text.charAt(nextChar) == 'u'); // \uuuu0061 is a legal unicode escape
     if (nextChar == i + 1 || nextChar + 3 >= length) {
       continue;
     }
     if (StringUtil.isHexDigit(text.charAt(nextChar))
         && StringUtil.isHexDigit(text.charAt(nextChar + 1))
         && StringUtil.isHexDigit(text.charAt(nextChar + 2))
         && StringUtil.isHexDigit(text.charAt(nextChar + 3))) {
       final int escapeEnd = nextChar + 4;
       final char d = (char) Integer.parseInt(text.substring(nextChar, escapeEnd), 16);
       if (Character.isISOControl(d)) {
         continue;
       }
       byteBuffer.clear();
       charBuffer.clear();
       charBuffer.put(d).rewind();
       final CoderResult coderResult = encoder.encode(charBuffer, byteBuffer, true);
       if (!coderResult.isUnmappable()) {
         final PsiElement element = file.findElementAt(i);
         if (element != null && isSuppressedFor(element)) {
           return;
         }
         registerErrorAtOffset(file, i, escapeEnd - i, Character.valueOf(d));
       }
     }
   }
 }
 @Override
 public Document getCachedDocument(@NotNull PsiFile file) {
   if (!file.isPhysical()) return null;
   VirtualFile vFile = file.getViewProvider().getVirtualFile();
   return FileDocumentManager.getInstance().getCachedDocument(vFile);
 }
 @Override
 public boolean isPhysical() {
   PsiFile file = getContainingFile();
   return file != null && file.isPhysical();
 }
  private void fireEvent(@NotNull PsiTreeChangeEventImpl event) {
    boolean isRealTreeChange =
        event.getCode() != PsiTreeChangeEventImpl.PsiEventType.PROPERTY_CHANGED
            && event.getCode() != PsiTreeChangeEventImpl.PsiEventType.BEFORE_PROPERTY_CHANGE;

    PsiFile file = event.getFile();
    if (file == null || file.isPhysical()) {
      ApplicationManager.getApplication().assertWriteAccessAllowed();
    }
    if (isRealTreeChange) {
      LOG.assertTrue(
          !myTreeChangeEventIsFiring, "Changes to PSI are not allowed inside event processing");
      myTreeChangeEventIsFiring = true;
    }
    try {
      for (PsiTreeChangePreprocessor preprocessor : myTreeChangePreprocessors) {
        preprocessor.treeChanged(event);
      }

      for (PsiTreeChangeListener listener : myTreeChangeListeners) {
        try {
          switch (event.getCode()) {
            case BEFORE_CHILD_ADDITION:
              listener.beforeChildAddition(event);
              break;

            case BEFORE_CHILD_REMOVAL:
              listener.beforeChildRemoval(event);
              break;

            case BEFORE_CHILD_REPLACEMENT:
              listener.beforeChildReplacement(event);
              break;

            case BEFORE_CHILD_MOVEMENT:
              listener.beforeChildMovement(event);
              break;

            case BEFORE_CHILDREN_CHANGE:
              listener.beforeChildrenChange(event);
              break;

            case BEFORE_PROPERTY_CHANGE:
              listener.beforePropertyChange(event);
              break;

            case CHILD_ADDED:
              listener.childAdded(event);
              break;

            case CHILD_REMOVED:
              listener.childRemoved(event);
              break;

            case CHILD_REPLACED:
              listener.childReplaced(event);
              break;

            case CHILD_MOVED:
              listener.childMoved(event);
              break;

            case CHILDREN_CHANGED:
              listener.childrenChanged(event);
              break;

            case PROPERTY_CHANGED:
              listener.propertyChanged(event);
              break;
          }
        } catch (Exception e) {
          LOG.error(e);
        }
      }
    } finally {
      if (isRealTreeChange) {
        myTreeChangeEventIsFiring = false;
      }
    }
  }
  @NotNull
  protected DaemonCodeAnalyzerStatus getDaemonCodeAnalyzerStatus(
      @NotNull SeverityRegistrar severityRegistrar) {
    DaemonCodeAnalyzerStatus status = new DaemonCodeAnalyzerStatus();
    if (myFile == null) {
      status.reasonWhyDisabled = "No file";
      status.errorAnalyzingFinished = true;
      return status;
    }
    if (myProject != null && myProject.isDisposed()) {
      status.reasonWhyDisabled = "Project is disposed";
      status.errorAnalyzingFinished = true;
      return status;
    }
    if (!myDaemonCodeAnalyzer.isHighlightingAvailable(myFile)) {
      if (!myFile.isPhysical()) {
        status.reasonWhyDisabled = "File is generated";
        status.errorAnalyzingFinished = true;
        return status;
      } else if (myFile instanceof PsiCompiledElement) {
        status.reasonWhyDisabled = "File is decompiled";
        status.errorAnalyzingFinished = true;
        return status;
      }
      final FileType fileType = myFile.getFileType();
      if (fileType.isBinary()) {
        status.reasonWhyDisabled = "File is binary";
        status.errorAnalyzingFinished = true;
        return status;
      }
      status.reasonWhyDisabled = "Highlighting is disabled for this file";
      status.errorAnalyzingFinished = true;
      return status;
    }

    FileViewProvider provider = myFile.getViewProvider();
    Set<Language> languages = provider.getLanguages();
    HighlightingSettingsPerFile levelSettings = HighlightingSettingsPerFile.getInstance(myProject);
    boolean shouldHighlight = languages.isEmpty();
    for (Language language : languages) {
      PsiFile root = provider.getPsi(language);
      FileHighlightingSetting level = levelSettings.getHighlightingSettingForRoot(root);
      shouldHighlight |= level != FileHighlightingSetting.SKIP_HIGHLIGHTING;
    }
    if (!shouldHighlight) {
      status.reasonWhyDisabled = "Highlighting level is None";
      status.errorAnalyzingFinished = true;
      return status;
    }

    if (HeavyProcessLatch.INSTANCE.isRunning()) {
      status.reasonWhySuspended =
          StringUtil.defaultIfEmpty(
              HeavyProcessLatch.INSTANCE.getRunningOperationName(), "Heavy operation is running");
      status.errorAnalyzingFinished = true;
      return status;
    }

    status.errorCount = errorCount.clone();
    fillDaemonCodeAnalyzerErrorsStatus(status, severityRegistrar);
    List<TextEditorHighlightingPass> passes =
        myDaemonCodeAnalyzer.getPassesToShowProgressFor(myDocument);
    status.passStati =
        passes.isEmpty()
            ? Collections.<ProgressableTextEditorHighlightingPass>emptyList()
            : new ArrayList<>(passes.size());
    //noinspection ForLoopReplaceableByForEach
    for (int i = 0; i < passes.size(); i++) {
      TextEditorHighlightingPass tepass = passes.get(i);
      if (!(tepass instanceof ProgressableTextEditorHighlightingPass)) continue;
      ProgressableTextEditorHighlightingPass pass = (ProgressableTextEditorHighlightingPass) tepass;

      if (pass.getProgress() < 0) continue;
      status.passStati.add(pass);
    }
    status.errorAnalyzingFinished = myDaemonCodeAnalyzer.isAllAnalysisFinished(myFile);
    status.reasonWhySuspended =
        myDaemonCodeAnalyzer.isUpdateByTimerEnabled() ? null : "Highlighting is paused temporarily";

    return status;
  }