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