public static void doActualPsiChange(@NotNull final PsiFile file, final DiffLog diffLog) { file.getViewProvider().beforeContentsSynchronized(); try { final Document document = file.getViewProvider().getDocument(); PsiDocumentManagerImpl documentManager = (PsiDocumentManagerImpl) PsiDocumentManager.getInstance(file.getProject()); PsiToDocumentSynchronizer.DocumentChangeTransaction transaction = documentManager.getSynchronizer().getTransaction(document); final PsiFileImpl fileImpl = (PsiFileImpl) file; if (transaction == null) { final PomModel model = PomManager.getModel(fileImpl.getProject()); model.runTransaction( new PomTransactionBase(fileImpl, model.getModelAspect(TreeAspect.class)) { @Override public PomModelEvent runInner() { return new TreeAspectEvent(model, diffLog.performActualPsiChange(file)); } }); } else { diffLog.performActualPsiChange(file); } } catch (IncorrectOperationException e) { LOG.error(e); } }
@Nullable @Override public Document getDocument(@NotNull PsiFile file) { if (file instanceof PsiBinaryFile) return null; Document document = getCachedDocument(file); if (document != null) { if (!file.getViewProvider().isPhysical() && document.getUserData(HARD_REF_TO_PSI) == null) { cachePsi(document, file); } return document; } if (!file.getViewProvider().isEventSystemEnabled()) return null; document = FileDocumentManager.getInstance().getDocument(file.getViewProvider().getVirtualFile()); if (document != null) { if (document.getTextLength() != file.getTextLength()) { throw new AssertionError( "Modified PSI with no document: " + file + "; physical=" + file.getViewProvider().isPhysical()); } if (!file.getViewProvider().isPhysical()) { cachePsi(document, file); } } return document; }
public boolean commitTransaction(final Document document) { ApplicationManager.getApplication().assertIsDispatchThread(); final DocumentChangeTransaction documentChangeTransaction = removeTransaction(document); if (documentChangeTransaction == null) return false; final PsiFile changeScope = documentChangeTransaction.myChangeScope; try { mySyncDocument = document; final PsiTreeChangeEventImpl fakeEvent = new PsiTreeChangeEventImpl(changeScope.getManager()); fakeEvent.setParent(changeScope); fakeEvent.setFile(changeScope); checkPsiModificationAllowed(fakeEvent); doSync( fakeEvent, true, new DocSyncAction() { @Override public void syncDocument( @NotNull Document document, @NotNull PsiTreeChangeEventImpl event) { doCommitTransaction(document, documentChangeTransaction); } }); myBus .syncPublisher(PsiDocumentTransactionListener.TOPIC) .transactionCompleted(document, changeScope); } catch (Throwable e) { myPsiDocumentManager.forceReload( changeScope.getViewProvider().getVirtualFile(), changeScope.getViewProvider()); ExceptionUtil.rethrowAllAsUnchecked(e); } finally { mySyncDocument = null; } return true; }
@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; }
private boolean checkMovingInsideOutside( PsiFile file, final Editor editor, LineRange range, @NotNull final MoveInfo info, final boolean down) { final int offset = editor.getCaretModel().getOffset(); PsiElement elementAtOffset = file.getViewProvider().findElementAt(offset, StdLanguages.JAVA); if (elementAtOffset == null) return false; PsiElement guard = elementAtOffset; do { guard = PsiTreeUtil.getParentOfType( guard, PsiMethod.class, PsiClassInitializer.class, PsiClass.class, PsiComment.class); } while (guard instanceof PsiAnonymousClass); PsiElement brace = itIsTheClosingCurlyBraceWeAreMoving(file, editor); if (brace != null) { int line = editor.getDocument().getLineNumber(offset); final LineRange toMove = new LineRange(line, line + 1); toMove.firstElement = toMove.lastElement = brace; info.toMove = toMove; } // cannot move in/outside method/class/initializer/comment if (!calcInsertOffset(file, editor, info.toMove, info, down)) return false; int insertOffset = down ? getLineStartSafeOffset(editor.getDocument(), info.toMove2.endLine) : editor.getDocument().getLineStartOffset(info.toMove2.startLine); PsiElement elementAtInsertOffset = file.getViewProvider().findElementAt(insertOffset, StdLanguages.JAVA); PsiElement newGuard = elementAtInsertOffset; do { newGuard = PsiTreeUtil.getParentOfType( newGuard, PsiMethod.class, PsiClassInitializer.class, PsiClass.class, PsiComment.class); } while (newGuard instanceof PsiAnonymousClass); if (brace != null && PsiTreeUtil.getParentOfType(brace, PsiCodeBlock.class, false) != PsiTreeUtil.getParentOfType(elementAtInsertOffset, PsiCodeBlock.class, false)) { info.indentSource = true; } if (newGuard == guard && isInside(insertOffset, newGuard) == isInside(offset, guard)) return true; // moving in/out nested class is OK if (guard instanceof PsiClass && guard.getParent() instanceof PsiClass) return true; if (newGuard instanceof PsiClass && newGuard.getParent() instanceof PsiClass) return true; return false; }
public static boolean isClassEquivalentTo(@NotNull PsiClass aClass, PsiElement another) { if (aClass == another) return true; if (!(another instanceof PsiClass)) return false; String name1 = aClass.getName(); if (name1 == null) return false; if (!another.isValid()) return false; String name2 = ((PsiClass) another).getName(); if (name2 == null) return false; if (name1.hashCode() != name2.hashCode()) return false; if (!name1.equals(name2)) return false; String qName1 = aClass.getQualifiedName(); String qName2 = ((PsiClass) another).getQualifiedName(); if (qName1 == null || qName2 == null) { //noinspection StringEquality if (qName1 != qName2) return false; if (aClass instanceof PsiTypeParameter && another instanceof PsiTypeParameter) { PsiTypeParameter p1 = (PsiTypeParameter) aClass; PsiTypeParameter p2 = (PsiTypeParameter) another; return p1.getIndex() == p2.getIndex() && aClass.getManager().areElementsEquivalent(p1.getOwner(), p2.getOwner()); } else { return false; } } if (qName1.hashCode() != qName2.hashCode() || !qName1.equals(qName2)) { return false; } if (originalElement(aClass).equals(originalElement((PsiClass) another))) { return true; } final PsiFile file1 = aClass.getContainingFile().getOriginalFile(); final PsiFile file2 = another.getContainingFile().getOriginalFile(); // see com.intellij.openapi.vcs.changes.PsiChangeTracker // see com.intellij.psi.impl.PsiFileFactoryImpl#createFileFromText(CharSequence,PsiFile) final PsiFile original1 = file1.getUserData(PsiFileFactory.ORIGINAL_FILE); final PsiFile original2 = file2.getUserData(PsiFileFactory.ORIGINAL_FILE); if (original1 == original2 && original1 != null || original1 == file2 || original2 == file1 || file1 == file2) { return compareClassSeqNumber(aClass, (PsiClass) another); } final FileIndexFacade fileIndex = ServiceManager.getService(file1.getProject(), FileIndexFacade.class); final VirtualFile vfile1 = file1.getViewProvider().getVirtualFile(); final VirtualFile vfile2 = file2.getViewProvider().getVirtualFile(); boolean lib1 = fileIndex.isInLibraryClasses(vfile1); boolean lib2 = fileIndex.isInLibraryClasses(vfile2); return (fileIndex.isInSource(vfile1) || lib1) && (fileIndex.isInSource(vfile2) || lib2); }
@Nullable public static String findUri(PsiFile file, int offset) { PsiReference currentRef = file.getViewProvider().findReferenceAt(offset, file.getLanguage()); if (currentRef == null) currentRef = file.getViewProvider().findReferenceAt(offset); if (currentRef instanceof URLReference || currentRef instanceof DependentNSReference) { return currentRef.getCanonicalText(); } return null; }
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; }
public boolean isErrorAnalyzingFinished(@NotNull PsiFile file) { if (myDisposed) return false; Document document = PsiDocumentManager.getInstance(myProject).getCachedDocument(file); return document != null && document.getModificationStamp() == file.getViewProvider().getModificationStamp() && myFileStatusMap.getFileDirtyScope(document, Pass.UPDATE_ALL) == null; }
// returns (injected psi, leaf element at the offset, language of the leaf element) // since findElementAt() is expensive, we trying to reuse its result @NotNull private static Trinity<PsiElement, PsiElement, Language> tryOffset( @NotNull PsiFile hostFile, final int offset, @NotNull PsiDocumentManager documentManager) { FileViewProvider provider = hostFile.getViewProvider(); Language leafLanguage = null; PsiElement leafElement = null; for (Language language : provider.getLanguages()) { PsiElement element = provider.findElementAt(offset, language); if (element != null) { if (leafLanguage == null) { leafLanguage = language; leafElement = element; } PsiElement injected = findInside(element, hostFile, offset, documentManager); if (injected != null) return Trinity.create(injected, element, language); } // maybe we are at the border between two psi elements, then try to find injection at the end // of the left element if (offset != 0 && (element == null || element.getTextRange().getStartOffset() == offset)) { PsiElement leftElement = provider.findElementAt(offset - 1, language); if (leftElement != null && leftElement.getTextRange().getEndOffset() == offset) { PsiElement injected = findInside(leftElement, hostFile, offset, documentManager); if (injected != null) return Trinity.create(injected, element, language); } } } return Trinity.create(null, leafElement, leafLanguage); }
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); } }
@Override @Nullable protected TextRange surroundStatement( @NotNull Project project, @NotNull Editor editor, @NotNull PsiElement[] elements) throws IncorrectOperationException { PyTryExceptStatement tryStatement = PyElementGenerator.getInstance(project) .createFromText(LanguageLevel.getDefault(), PyTryExceptStatement.class, getTemplate()); final PsiElement parent = elements[0].getParent(); final PyStatementList statementList = tryStatement.getTryPart().getStatementList(); statementList.addRange(elements[0], elements[elements.length - 1]); statementList.getFirstChild().delete(); tryStatement = (PyTryExceptStatement) parent.addBefore(tryStatement, elements[0]); parent.deleteChildRange(elements[0], elements[elements.length - 1]); final PsiFile psiFile = parent.getContainingFile(); final Document document = psiFile.getViewProvider().getDocument(); final TextRange range = tryStatement.getTextRange(); assert document != null; final RangeMarker rangeMarker = document.createRangeMarker(range); final PsiElement element = psiFile.findElementAt(rangeMarker.getStartOffset()); tryStatement = PsiTreeUtil.getParentOfType(element, PyTryExceptStatement.class); if (tryStatement != null) { return getResultRange(tryStatement); } return null; }
@Override @Nullable public ObjectStubTree readOrBuild( Project project, final VirtualFile vFile, @Nullable PsiFile psiFile) { final ObjectStubTree fromIndices = readFromVFile(project, vFile); if (fromIndices != null) { return fromIndices; } try { final FileContent fc = new FileContentImpl(vFile, vFile.contentsToByteArray()); fc.putUserData(IndexingDataKeys.PROJECT, project); if (psiFile != null && !vFile.getFileType().isBinary()) { fc.putUserData( IndexingDataKeys.FILE_TEXT_CONTENT_KEY, psiFile.getViewProvider().getContents()); // but don't reuse psiFile itself to avoid loading its contents. If we load AST, the stub // will be thrown out anyway. } Stub element = StubTreeBuilder.buildStubTree(fc); if (element instanceof PsiFileStub) { StubTree tree = new StubTree((PsiFileStub) element); tree.setDebugInfo("created from file content"); return tree; } } catch (IOException e) { LOG.info( e); // content can be not cached yet, and the file can be deleted on disk already, without // refresh } return null; }
private static boolean navigateInCurrentEditor( @NotNull PsiElement element, @NotNull PsiFile currentFile, @NotNull Editor currentEditor) { if (element.getContainingFile() == currentFile) { int offset = element.getTextOffset(); PsiElement leaf = currentFile.findElementAt(offset); // check that element is really physically inside the file // there are fake elements with custom navigation (e.g. opening URL in browser) that override // getContainingFile for various reasons if (leaf != null && PsiTreeUtil.isAncestor(element, leaf, false)) { Project project = element.getProject(); CommandProcessor.getInstance() .executeCommand( project, () -> { IdeDocumentHistory.getInstance(project).includeCurrentCommandAsNavigation(); new OpenFileDescriptor( project, currentFile.getViewProvider().getVirtualFile(), offset) .navigateIn(currentEditor); }, "", null); return true; } } return false; }
@Nullable public static <E extends PsiElement> E findArgumentList( PsiFile file, int offset, int lbraceOffset) { if (file == null) return null; ParameterInfoHandler[] handlers = ShowParameterInfoHandler.getHandlers( file.getProject(), PsiUtilCore.getLanguageAtOffset(file, offset), file.getViewProvider().getBaseLanguage()); if (handlers != null) { for (ParameterInfoHandler handler : handlers) { if (handler instanceof ParameterInfoHandlerWithTabActionSupport) { final ParameterInfoHandlerWithTabActionSupport parameterInfoHandler2 = (ParameterInfoHandlerWithTabActionSupport) handler; // please don't remove typecast in the following line; it's required to compile the code // under old JDK 6 versions final E e = (E) ParameterInfoUtils.findArgumentList( file, offset, lbraceOffset, parameterInfoHandler2); if (e != null) return e; } } } return null; }
@Nullable public static Commenter getCommenter( final PsiFile file, final Editor editor, final Language lineStartLanguage, final Language lineEndLanguage) { final FileViewProvider viewProvider = file.getViewProvider(); for (MultipleLangCommentProvider provider : MultipleLangCommentProvider.EP_NAME.getExtensions()) { if (provider.canProcess(file, viewProvider)) { return provider.getLineCommenter(file, editor, lineStartLanguage, lineEndLanguage); } } final Language fileLanguage = file.getLanguage(); Language lang = lineStartLanguage == null || LanguageCommenters.INSTANCE.forLanguage(lineStartLanguage) == null || fileLanguage.getBaseLanguage() == lineStartLanguage // file language is a more specific dialect of the line // language ? fileLanguage : lineStartLanguage; if (viewProvider instanceof TemplateLanguageFileViewProvider && lang == ((TemplateLanguageFileViewProvider) viewProvider).getTemplateDataLanguage()) { lang = viewProvider.getBaseLanguage(); } return LanguageCommenters.INSTANCE.forLanguage(lang); }
private void doSync( @NotNull final PsiTreeChangeEvent event, boolean force, @NotNull final DocSyncAction syncAction) { if (!toProcessPsiEvent()) return; final PsiFile psiFile = event.getFile(); if (!(psiFile instanceof PsiFileEx) || !((PsiFileEx) psiFile).isContentsLoaded()) return; final DocumentEx document = getCachedDocument(psiFile, force); if (document == null) return; performAtomically( psiFile, new Runnable() { @Override public void run() { syncAction.syncDocument(document, (PsiTreeChangeEventImpl) event); } }); final boolean insideTransaction = myTransactionsMap.containsKey(document); if (!insideTransaction) { document.setModificationStamp(psiFile.getViewProvider().getModificationStamp()); } }
public boolean isAllAnalysisFinished(@NotNull PsiFile file) { if (myDisposed) return false; Document document = PsiDocumentManager.getInstance(myProject).getCachedDocument(file); return document != null && document.getModificationStamp() == file.getViewProvider().getModificationStamp() && myFileStatusMap.allDirtyScopesAreNull(document); }
@Nullable private PsiClass mapClass(@NotNull PsiClass psiClass) { String qualifiedName = psiClass.getQualifiedName(); if (qualifiedName == null) { return psiClass; } PsiFile file = psiClass.getContainingFile(); if (file == null || !file.getViewProvider().isPhysical()) { return psiClass; } final VirtualFile vFile = file.getVirtualFile(); if (vFile == null) { return psiClass; } final FileIndexFacade index = FileIndexFacade.getInstance(file.getProject()); if (!index.isInSource(vFile) && !index.isInLibrarySource(vFile) && !index.isInLibraryClasses(vFile)) { return psiClass; } return JavaPsiFacade.getInstance(psiClass.getProject()) .findClass(qualifiedName, myResolveScope); }
private static VirtualFile getConsoleFile(PsiFile psiFile) { VirtualFile file = psiFile.getViewProvider().getVirtualFile(); if (file instanceof LightVirtualFile) { file = ((LightVirtualFile) file).getOriginalFile(); } return file; }
private static void logStats(Collection<PsiFile> otherFiles, long start) { long time = System.currentTimeMillis() - start; final Multiset<String> stats = HashMultiset.create(); for (PsiFile file : otherFiles) { stats.add( StringUtil.notNullize(file.getViewProvider().getVirtualFile().getExtension()) .toLowerCase()); } List<String> extensions = ContainerUtil.newArrayList(stats.elementSet()); Collections.sort( extensions, new Comparator<String>() { @Override public int compare(String o1, String o2) { return stats.count(o2) - stats.count(o1); } }); String message = "Search in " + otherFiles.size() + " files with unknown types took " + time + "ms.\n" + "Mapping their extensions to an existing file type (e.g. Plain Text) might speed up the search.\n" + "Most frequent non-indexed file extensions: "; for (int i = 0; i < Math.min(10, extensions.size()); i++) { String extension = extensions.get(i); message += extension + "(" + stats.count(extension) + ") "; } LOG.info(message); }
@NotNull private static String[] collectNamesToImport( @NotNull PsiJavaFile file, @NotNull Set<String> namesToImportStaticly) { Set<String> names = new THashSet<String>(); final JspFile jspFile = JspPsiUtil.getJspFile(file); collectNamesToImport(names, file, namesToImportStaticly, jspFile); if (jspFile != null) { PsiFile[] files = ArrayUtil.mergeArrays( JspSpiUtil.getIncludingFiles(jspFile), JspSpiUtil.getIncludedFiles(jspFile), PsiFile.class); for (PsiFile includingFile : files) { final PsiFile javaRoot = includingFile.getViewProvider().getPsi(StdLanguages.JAVA); if (javaRoot instanceof PsiJavaFile && file != javaRoot) { collectNamesToImport(names, (PsiJavaFile) javaRoot, namesToImportStaticly, jspFile); } } } addUnresolvedImportNames(names, file, namesToImportStaticly); return ArrayUtil.toStringArray(names); }
@Nullable private static PsiFile getRoot(final PsiFile file, final Editor editor) { if (file == null) return null; int offset = editor.getCaretModel().getOffset(); if (offset == editor.getDocument().getTextLength()) offset--; if (offset < 0) return null; PsiElement leafElement = file.findElementAt(offset); if (leafElement == null) return null; if (leafElement.getLanguage() instanceof DependentLanguage) { leafElement = file.getViewProvider().findElementAt(offset, file.getViewProvider().getBaseLanguage()); if (leafElement == null) return null; } ASTNode node = leafElement.getNode(); if (node == null) return null; return (PsiFile) PsiUtilBase.getRoot(node).getPsi(); }
private JavaResolveResult advancedResolveInner(final PsiElement psiElement, final String qName) { final PsiManager manager = psiElement.getManager(); final GlobalSearchScope scope = getScope(); if (myIndex == myJavaClassReferenceSet.getReferences().length - 1) { final PsiClass aClass = JavaPsiFacade.getInstance(manager.getProject()).findClass(qName, scope); if (aClass != null) { return new ClassCandidateInfo(aClass, PsiSubstitutor.EMPTY, false, psiElement); } else { if (!JavaClassReferenceProvider.ADVANCED_RESOLVE.getBooleanValue(getOptions())) { return JavaResolveResult.EMPTY; } } } PsiElement resolveResult = JavaPsiFacade.getInstance(manager.getProject()).findPackage(qName); if (resolveResult == null) { resolveResult = JavaPsiFacade.getInstance(manager.getProject()).findClass(qName, scope); } if (myInStaticImport && resolveResult == null) { resolveResult = resolveMember(qName, manager, getElement().getResolveScope()); } if (resolveResult == null) { PsiFile containingFile = psiElement.getContainingFile(); if (containingFile instanceof PsiJavaFile) { if (containingFile instanceof JspFile) { containingFile = containingFile.getViewProvider().getPsi(StdLanguages.JAVA); if (containingFile == null) return JavaResolveResult.EMPTY; } final ClassResolverProcessor processor = new ClassResolverProcessor(getCanonicalText(), psiElement); containingFile.processDeclarations(processor, ResolveState.initial(), null, psiElement); if (processor.getResult().length == 1) { final JavaResolveResult javaResolveResult = processor.getResult()[0]; if (javaResolveResult != JavaResolveResult.EMPTY && getOptions() != null) { final Boolean value = JavaClassReferenceProvider.RESOLVE_QUALIFIED_CLASS_NAME.getValue(getOptions()); final PsiClass psiClass = (PsiClass) javaResolveResult.getElement(); if (value != null && value.booleanValue() && psiClass != null) { final String qualifiedName = psiClass.getQualifiedName(); if (!qName.equals(qualifiedName)) { return JavaResolveResult.EMPTY; } } } return javaResolveResult; } } } return resolveResult != null ? new CandidateInfo(resolveResult, PsiSubstitutor.EMPTY, false, false, psiElement) : JavaResolveResult.EMPTY; }
private static boolean isCopyUpToDate(Document document, @NotNull PsiFile file) { if (!file.isValid()) { return false; } // the psi file cache might have been cleared by some external activity, // in which case PSI-document sync may stop working PsiFile current = PsiDocumentManager.getInstance(file.getProject()).getPsiFile(document); return current != null && current.getViewProvider().getPsi(file.getLanguage()) == file; }
private static int getNewIndent(final PsiFile psiFile, final int firstWhitespace) { final Document document = psiFile.getViewProvider().getDocument(); final int startOffset = document.getLineStartOffset(document.getLineNumber(firstWhitespace)); int endOffset = startOffset; final CharSequence charsSequence = document.getCharsSequence(); while (Character.isWhitespace(charsSequence.charAt(endOffset++))) ; final String newIndentStr = charsSequence.subSequence(startOffset, endOffset - 1).toString(); return IndentHelperImpl.getIndent( psiFile.getProject(), psiFile.getFileType(), newIndentStr, true); }
public static FormattingDocumentModelImpl createOn(PsiFile file) { Document document = getDocumentToBeUsedFor(file); if (document != null) { checkDocument(file, document); return new FormattingDocumentModelImpl(document, file); } else { return new FormattingDocumentModelImpl( new DocumentImpl(file.getViewProvider().getContents(), true), file); } }
@NotNull private static FileHighlightingSetting[] getDefaults(@NotNull PsiFile file) { final int rootsCount = file.getViewProvider().getLanguages().size(); final FileHighlightingSetting[] fileHighlightingSettings = new FileHighlightingSetting[rootsCount]; for (int i = 0; i < fileHighlightingSettings.length; i++) { fileHighlightingSettings[i] = FileHighlightingSetting.FORCE_HIGHLIGHTING; } return fileHighlightingSettings; }
@Nullable @Override public Document getDocument(@NotNull PsiFile file) { if (file instanceof PsiBinaryFile) return null; Document document = getCachedDocument(file); if (document != null) { if (!file.getViewProvider().isPhysical() && document.getUserData(HARD_REF_TO_PSI) == null) { PsiUtilCore.ensureValid(file); cachePsi(document, file); } return document; } FileViewProvider viewProvider = file.getViewProvider(); if (!viewProvider.isEventSystemEnabled()) return null; document = FileDocumentManager.getInstance().getDocument(viewProvider.getVirtualFile()); if (document != null) { if (document.getTextLength() != file.getTextLength()) { String message = "Document/PSI mismatch: " + file + " (" + file.getClass() + "); physical=" + viewProvider.isPhysical(); if (document.getTextLength() + file.getTextLength() < 8096) { message += "\n=== document ===\n" + document.getText() + "\n=== PSI ===\n" + file.getText(); } throw new AssertionError(message); } if (!viewProvider.isPhysical()) { PsiUtilCore.ensureValid(file); cachePsi(document, file); file.putUserData(HARD_REF_TO_DOCUMENT, document); } } return document; }
public static void assertInvalidRanges( final int startOffset, final int newEndOffset, FormattingDocumentModel model, String message) { @NonNls final StringBuilder buffer = new StringBuilder(); buffer.append("Invalid formatting blocks:").append(message).append("\n"); buffer.append("Start offset:"); buffer.append(startOffset); buffer.append(" end offset:"); buffer.append(newEndOffset); buffer.append("\n"); int minOffset = Math.max(Math.min(startOffset, newEndOffset) - 20, 0); int maxOffset = Math.min(Math.max(startOffset, newEndOffset) + 20, model.getTextLength()); buffer .append("Affected text fragment:[") .append(minOffset) .append(",") .append(maxOffset) .append("] - '") .append(model.getText(new TextRange(minOffset, maxOffset))) .append("'\n"); final StringBuilder messageBuffer = new StringBuilder(); messageBuffer.append("Invalid ranges during formatting"); if (model instanceof FormattingDocumentModelImpl) { messageBuffer .append(" in ") .append(((FormattingDocumentModelImpl) model).getFile().getLanguage()); } buffer.append("File text:(").append(model.getTextLength()).append(")\n'"); buffer.append(model.getText(new TextRange(0, model.getTextLength())).toString()); buffer.append("'\n"); buffer.append("model (").append(model.getClass()).append("): ").append(model); Throwable currentThrowable = new Throwable(); if (model instanceof FormattingDocumentModelImpl) { final FormattingDocumentModelImpl modelImpl = (FormattingDocumentModelImpl) model; buffer.append("Psi Tree:\n"); final PsiFile file = modelImpl.getFile(); final List<PsiFile> roots = file.getViewProvider().getAllFiles(); for (PsiFile root : roots) { buffer.append("Root "); DebugUtil.treeToBuffer(buffer, root.getNode(), 0, false, true, true, true); } buffer.append('\n'); currentThrowable = makeLanguageStackTrace(currentThrowable, file); } LogMessageEx.error(LOG, messageBuffer.toString(), currentThrowable, buffer.toString()); }