// 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); }
private void checkPsiIsCorrect(final FileViewProvider key) { PsiFile actualPsi = key.getPsi(key.getBaseLanguage()); PsiTreeDebugBuilder treeDebugBuilder = new PsiTreeDebugBuilder().setShowErrorElements(false).setShowWhiteSpaces(false); String actualPsiTree = treeDebugBuilder.psiToString(actualPsi); String fileName = key.getVirtualFile().getName(); PsiFile psi = PsiFileFactory.getInstance(myProject) .createFileFromText( fileName, FileTypeManager.getInstance().getFileTypeByFileName(fileName), actualPsi.getNode().getText(), LocalTimeCounter.currentTime(), false); if (actualPsi.getClass().equals(psi.getClass())) { String expectedPsi = treeDebugBuilder.psiToString(psi); if (!expectedPsi.equals(actualPsiTree)) { myReformatElements.clear(); assert expectedPsi.equals(actualPsiTree) : "Refactored psi should be the same as result of parsing"; } } }
@Override @SuppressWarnings({"CloneDoesntDeclareCloneNotSupportedException", "CloneDoesntCallSuperClone"}) protected PsiFileImpl clone() { FileViewProvider viewProvider = getViewProvider(); FileViewProvider providerCopy = viewProvider.clone(); final Language language = getLanguage(); if (providerCopy == null) { throw new AssertionError( "Unable to clone the view provider: " + viewProvider + "; " + language); } PsiFileImpl clone = BlockSupportImpl.getFileCopy(this, providerCopy); copyCopyableDataTo(clone); if (getTreeElement() != null) { // not set by provider in clone final FileElement treeClone = (FileElement) calcTreeElement().clone(); clone.setTreeElementPointer( treeClone); // should not use setTreeElement here because cloned file still have // VirtualFile (SCR17963) treeClone.setPsi(clone); } if (viewProvider.isEventSystemEnabled()) { clone.myOriginalFile = this; } else if (myOriginalFile != null) { clone.myOriginalFile = myOriginalFile; } return clone; }
@Override public void beforeDocumentChange(DocumentEvent event) { final Document document = event.getDocument(); final FileViewProvider viewProvider = getCachedViewProvider(document); if (viewProvider == null) return; if (!isRelevant(viewProvider)) return; VirtualFile virtualFile = viewProvider.getVirtualFile(); if (virtualFile.getFileType().isBinary()) return; final List<PsiFile> files = viewProvider.getAllFiles(); PsiFile psiCause = null; for (PsiFile file : files) { mySmartPointerManager.fastenBelts(file, event.getOffset(), null); if (TextBlock.get(file).isLocked()) { psiCause = file; } } if (psiCause == null) { beforeDocumentChangeOnUnlockedDocument(viewProvider); } ((SingleRootFileViewProvider) viewProvider).beforeDocumentChanged(psiCause); }
@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 doPostponedFormattingInner(final FileViewProvider key) { final List<ASTNode> astNodes = myReformatElements.remove(key); final Document document = key.getDocument(); // Sort ranges by end offsets so that we won't need any offset adjustment after reformat or // reindent if (document == null) return; final VirtualFile virtualFile = key.getVirtualFile(); if (!virtualFile.isValid()) return; final TreeSet<PostprocessFormattingTask> postProcessTasks = new TreeSet<PostprocessFormattingTask>(); Collection<Disposable> toDispose = ContainerUtilRt.newArrayList(); try { // process all roots in viewProvider to find marked for reformat before elements and create // appropriate range markers handleReformatMarkers(key, postProcessTasks); toDispose.addAll(postProcessTasks); // then we create ranges by changed nodes. One per node. There ranges can intersect. Ranges // are sorted by end offset. if (astNodes != null) createActionsMap(astNodes, key, postProcessTasks); if ("true".equals(System.getProperty("check.psi.is.valid")) && ApplicationManager.getApplication().isUnitTestMode()) { checkPsiIsCorrect(key); } while (!postProcessTasks.isEmpty()) { // now we have to normalize actions so that they not intersect and ordered in most // appropriate way // (free reformatting -> reindent -> formatting under reindent) final List<PostponedAction> normalizedActions = normalizeAndReorderPostponedActions(postProcessTasks, document); toDispose.addAll(normalizedActions); // only in following loop real changes in document are made for (final PostponedAction normalizedAction : normalizedActions) { CodeStyleSettings settings = CodeStyleSettingsManager.getSettings(myPsiManager.getProject()); boolean old = settings.ENABLE_JAVADOC_FORMATTING; settings.ENABLE_JAVADOC_FORMATTING = false; try { normalizedAction.execute(key); } finally { settings.ENABLE_JAVADOC_FORMATTING = old; } } } } finally { for (Disposable disposable : toDispose) { //noinspection SSBasedInspection disposable.dispose(); } } }
@Override public boolean isValid() { FileViewProvider provider = getViewProvider(); final VirtualFile vFile = provider.getVirtualFile(); if (!vFile.isValid()) return false; if (!provider.isEventSystemEnabled()) return true; // "dummy" file if (myManager.getProject().isDisposed()) return false; return isPsiUpToDate(vFile); }
protected boolean isPsiUpToDate(@NotNull VirtualFile vFile) { final FileViewProvider provider = myManager.findViewProvider(vFile); Language language = getLanguage(); if (provider == null || provider.getPsi(language) == this) { // provider == null in tests return true; } Language baseLanguage = provider.getBaseLanguage(); return baseLanguage != language && provider.getPsi(baseLanguage) == this; }
@NotNull private static DiffLog makeFullParse( @NotNull PsiFileImpl fileImpl, @NotNull CharSequence newFileText, @NotNull ProgressIndicator indicator, @NotNull CharSequence lastCommittedText) { if (fileImpl instanceof PsiCodeFragment) { FileElement parent = fileImpl.getTreeElement(); final FileElement holderElement = new DummyHolder(fileImpl.getManager(), null).getTreeElement(); holderElement.rawAddChildren( fileImpl.createContentLeafElement( holderElement.getCharTable().intern(newFileText, 0, newFileText.length()))); DiffLog diffLog = new DiffLog(); diffLog.appendReplaceFileElement(parent, (FileElement) holderElement.getFirstChildNode()); return diffLog; } else { FileViewProvider viewProvider = fileImpl.getViewProvider(); viewProvider.getLanguages(); FileType fileType = viewProvider.getVirtualFile().getFileType(); String fileName = fileImpl.getName(); final LightVirtualFile lightFile = new LightVirtualFile( fileName, fileType, newFileText, viewProvider.getVirtualFile().getCharset(), fileImpl.getViewProvider().getModificationStamp()); lightFile.setOriginalFile(viewProvider.getVirtualFile()); FileViewProvider copy = viewProvider.createCopy(lightFile); if (copy.isEventSystemEnabled()) { throw new AssertionError( "Copied view provider must be non-physical for reparse to deliver correct events: " + viewProvider); } copy.getLanguages(); SingleRootFileViewProvider.doNotCheckFileSizeLimit( lightFile); // optimization: do not convert file contents to bytes to determine if we // should codeinsight it PsiFileImpl newFile = getFileCopy(fileImpl, copy); newFile.setOriginalFile(fileImpl); final FileElement newFileElement = (FileElement) newFile.getNode(); final FileElement oldFileElement = (FileElement) fileImpl.getNode(); if (!lastCommittedText.toString().equals(oldFileElement.getText())) { throw new IncorrectOperationException(); } DiffLog diffLog = mergeTrees(fileImpl, oldFileElement, newFileElement, indicator, lastCommittedText); ((PsiManagerEx) fileImpl.getManager()).getFileManager().setViewProvider(lightFile, null); return diffLog; } }
private static PsiElement[] getElementsIntersectingRange( PsiFile file, final int startOffset, final int endOffset) { final FileViewProvider viewProvider = file.getViewProvider(); final Set<PsiElement> result = new LinkedHashSet<PsiElement>(); for (Language language : viewProvider.getLanguages()) { final PsiFile psiRoot = viewProvider.getPsi(language); if (HighlightingLevelManager.getInstance(file.getProject()).shouldInspect(psiRoot)) { result.addAll( CollectHighlightsUtil.getElementsInRange(psiRoot, startOffset, endOffset, true)); } } return PsiUtilCore.toPsiElementArray(result); }
@NotNull private static PsiAnchor doCreateAnchor(@NotNull PsiElement element) { if (element instanceof PsiFile) { VirtualFile virtualFile = ((PsiFile) element).getVirtualFile(); if (virtualFile != null) return new PsiFileReference(virtualFile, (PsiFile) element); return new HardReference(element); } if (element instanceof PsiDirectory) { VirtualFile virtualFile = ((PsiDirectory) element).getVirtualFile(); return new PsiDirectoryReference(virtualFile, element.getProject()); } PsiFile file = element.getContainingFile(); if (file == null) { return new HardReference(element); } VirtualFile virtualFile = file.getVirtualFile(); if (virtualFile == null) return new HardReference(element); PsiAnchor stubRef = createStubReference(element, file); if (stubRef != null) return stubRef; if (!element.isPhysical()) { return wrapperOrHardReference(element); } TextRange textRange = element.getTextRange(); if (textRange == null) { return wrapperOrHardReference(element); } Language lang = null; final FileViewProvider viewProvider = file.getViewProvider(); for (Language l : viewProvider.getLanguages()) { if (viewProvider.getPsi(l) == file) { lang = l; break; } } if (lang == null) { return wrapperOrHardReference(element); } return new TreeRangeReference( file, textRange.getStartOffset(), textRange.getEndOffset(), AnchorTypeInfo.obtainInfo(element, lang), virtualFile); }
@Nullable public static PsiElement getNextSibling(PsiElement element) { if (element instanceof PsiFile) { final FileViewProvider viewProvider = ((PsiFile) element).getViewProvider(); element = viewProvider.getPsi(viewProvider.getBaseLanguage()); } if (element == null) return null; final PsiElement parent = element.getParent(); if (parent == null) return null; final PsiElement[] children = parent.getChildren(); final int index = getChildIndex(children, element); return 0 <= index && index < children.length - 1 ? children[index + 1] : null; }
@Override public void documentChanged(DocumentEvent event) { final Document document = event.getDocument(); final FileViewProvider viewProvider = getCachedViewProvider(document); if (viewProvider == null) return; if (!isRelevant(viewProvider)) return; ApplicationManager.getApplication().assertWriteAccessAllowed(); final List<PsiFile> files = viewProvider.getAllFiles(); boolean commitNecessary = true; for (PsiFile file : files) { mySmartPointerManager.unfastenBelts(file, event.getOffset()); final TextBlock textBlock = TextBlock.get(file); if (textBlock.isLocked()) { commitNecessary = false; continue; } textBlock.documentChanged(event); assert file instanceof PsiFileImpl || "mock.file".equals(file.getName()) && ApplicationManager.getApplication().isUnitTestMode() : event + "; file=" + file + "; allFiles=" + files + "; viewProvider=" + viewProvider; } boolean forceCommit = ApplicationManager.getApplication().hasWriteAction(ExternalChangeAction.class) && (SystemProperties.getBooleanProperty("idea.force.commit.on.external.change", false) || ApplicationManager.getApplication().isHeadlessEnvironment()); // Consider that it's worth to perform complete re-parse instead of merge if the whole document // text is replaced and // current document lines number is roughly above 5000. This makes sense in situations when // external change is performed // for the huge file (that causes the whole document to be reloaded and 'merge' way takes a // while to complete). if (event.isWholeTextReplaced() && document.getTextLength() > 100000) { document.putUserData(BlockSupport.DO_NOT_REPARSE_INCREMENTALLY, Boolean.TRUE); } if (commitNecessary) { myUncommittedDocuments.add(document); if (forceCommit) { commitDocument(document); } else if (!((DocumentEx) document).isInBulkUpdate()) { myDocumentCommitProcessor.commitAsynchronously(myProject, document, event); } } }
public void execute(FileViewProvider viewProvider) { final Document document = viewProvider.getDocument(); final PsiFile psiFile = viewProvider.getPsi(viewProvider.getBaseLanguage()); for (Pair<Integer, RangeMarker> integerRangeMarkerPair : myRangesToReindent) { RangeMarker marker = integerRangeMarkerPair.second; final CharSequence charsSequence = document.getCharsSequence().subSequence(marker.getStartOffset(), marker.getEndOffset()); final int oldIndent = integerRangeMarkerPair.first; final TextRange[] whitespaces = CharArrayUtil.getIndents(charsSequence, marker.getStartOffset()); final int indentAdjustment = getNewIndent(psiFile, marker.getStartOffset()) - oldIndent; if (indentAdjustment != 0) adjustIndentationInRange(psiFile, document, whitespaces, indentAdjustment); } }
private static Language findLanguage(PsiFile file) { FileViewProvider vp = file.getViewProvider(); Set<Language> languages = vp.getLanguages(); for (Language language : languages) { if (file.equals(vp.getPsi(language))) { return language; } } throw new AssertionError( "Non-retrievable file: " + file.getClass() + "; " + file.getLanguage() + "; " + languages); }
private static void handleReformatMarkers( final FileViewProvider key, final TreeSet<PostprocessFormattingTask> rangesToProcess) { final Document document = key.getDocument(); if (document == null) { return; } for (final FileElement fileElement : ((SingleRootFileViewProvider) key).getKnownTreeRoots()) { fileElement.acceptTree( new RecursiveTreeElementWalkingVisitor() { protected void visitNode(TreeElement element) { if (CodeEditUtil.isMarkedToReformatBefore(element)) { CodeEditUtil.markToReformatBefore(element, false); rangesToProcess.add( new ReformatWithHeadingWhitespaceTask( document.createRangeMarker( element.getStartOffset(), element.getStartOffset()))); } else if (CodeEditUtil.isMarkedToReformat(element)) { CodeEditUtil.markToReformat(element, false); rangesToProcess.add( new ReformatWithHeadingWhitespaceTask( document.createRangeMarker( element.getStartOffset(), element.getStartOffset() + element.getTextLength()))); } super.visitNode(element); } }); } }
@Override public void beforeDocumentChange(@NotNull DocumentEvent event) { if (myStopTrackingDocuments) return; final Document document = event.getDocument(); if (!(document instanceof DocumentWindow) && !myLastCommittedTexts.containsKey(document)) { myLastCommittedTexts.put( document, Pair.create(document.getImmutableCharSequence(), document.getModificationStamp())); } VirtualFile virtualFile = FileDocumentManager.getInstance().getFile(document); boolean isRelevant = virtualFile != null && isRelevant(virtualFile); final FileViewProvider viewProvider = getCachedViewProvider(document); boolean inMyProject = viewProvider != null && viewProvider.getManager() == myPsiManager; if (!isRelevant || !inMyProject) { return; } final List<PsiFile> files = viewProvider.getAllFiles(); PsiFile psiCause = null; for (PsiFile file : files) { if (file == null) { throw new AssertionError( "View provider " + viewProvider + " (" + viewProvider.getClass() + ") returned null in its files array: " + files + " for file " + viewProvider.getVirtualFile()); } if (mySynchronizer.isInsideAtomicChange(file)) { psiCause = file; } } if (psiCause == null) { beforeDocumentChangeOnUnlockedDocument(viewProvider); } ((SingleRootFileViewProvider) viewProvider).beforeDocumentChanged(psiCause); }
@Override public void visitFile(PsiFile file) { final VirtualFile virtualFile = file.getVirtualFile(); if (virtualFile != null) { String relative = ProjectUtilCore.displayUrlRelativeToProject( virtualFile, virtualFile.getPresentableUrl(), myProject, true, false); myContext.incrementJobDoneAmount(myContext.getStdJobDescriptors().BUILD_GRAPH, relative); } final FileViewProvider viewProvider = file.getViewProvider(); final Set<Language> relevantLanguages = viewProvider.getLanguages(); for (Language language : relevantLanguages) { visitElement(viewProvider.getPsi(language)); } myPsiManager.dropResolveCaches(); InjectedLanguageManager.getInstance(myProject).dropFileCaches(file); }
// consider injected elements public static PsiElement findElementAtNoCommit(@NotNull PsiFile file, int offset) { FileViewProvider viewProvider = file.getViewProvider(); Trinity<PsiElement, PsiElement, Language> result = null; if (!(viewProvider instanceof InjectedFileViewProvider)) { PsiDocumentManager documentManager = PsiDocumentManager.getInstance(file.getProject()); result = tryOffset(file, offset, documentManager); PsiElement injected = result.first; if (injected != null) { return injected; } } Language baseLanguage = viewProvider.getBaseLanguage(); if (result != null && baseLanguage == result.third) { return result.second; // already queried } return viewProvider.findElementAt(offset, baseLanguage); }
private static void mapJsp(FileContent inputData, final List<LinkInfo> result) { final FileViewProvider viewProvider = inputData.getPsiFile().getViewProvider(); PsiFile psiFile = null; if (viewProvider instanceof TemplateLanguageFileViewProvider) { final Language dataLanguage = ((TemplateLanguageFileViewProvider) viewProvider).getTemplateDataLanguage(); if (dataLanguage == HTMLLanguage.INSTANCE || dataLanguage == XHTMLLanguage.INSTANCE) { psiFile = viewProvider.getPsi(dataLanguage); } } else { psiFile = viewProvider.getPsi(viewProvider.getBaseLanguage()); } if (psiFile != null) { final XmlRecursiveElementVisitor visitor = new XmlRecursiveElementVisitor() { @Override public void visitXmlTag(XmlTag tag) { if (LINK.equalsIgnoreCase(tag.getLocalName())) { final String href = getAttributeValue(tag, HREF_ATTR); final String media = getAttributeValue(tag, MEDIA_ATTR); final String type = getAttributeValue(tag, TYPE_ATTR); final String rel = getAttributeValue(tag, REL_ATTR); final String title = getAttributeValue(tag, TITLE_ATTR); addResult( result, tag.getTextOffset(), href, media, type, rel, title, isHrefScripted(tag)); } super.visitXmlTag(tag); } }; psiFile.accept(visitor); } }
@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; }
protected boolean finishCommitInWriteAction( @NotNull final Document document, @NotNull final List<Processor<Document>> finishProcessors, final boolean synchronously) { if (myProject.isDisposed()) return false; assert !(document instanceof DocumentWindow); myIsCommitInProgress = true; boolean success = true; try { final FileViewProvider viewProvider = getCachedViewProvider(document); if (viewProvider != null) { for (Processor<Document> finishRunnable : finishProcessors) { success = finishRunnable.process(document); if (synchronously) { assert success : finishRunnable + " in " + finishProcessors; } if (!success) { break; } } if (success) { myLastCommittedTexts.remove(document); viewProvider.contentsSynchronized(); } } else { handleCommitWithoutPsi(document); } } finally { myDocumentCommitProcessor.log( "in PDI.finishDoc: ", null, synchronously, success, myUncommittedDocuments); if (success) { myUncommittedDocuments.remove(document); myDocumentCommitProcessor.log( "in PDI.finishDoc: removed doc", null, synchronously, success, myUncommittedDocuments); } myIsCommitInProgress = false; myDocumentCommitProcessor.log( "in PDI.finishDoc: exit", null, synchronously, success, myUncommittedDocuments); } return success; }
private CodeFormatterFacade getFormatterFacade(final FileViewProvider viewProvider) { final CodeStyleSettings styleSettings = CodeStyleSettingsManager.getSettings(myPsiManager.getProject()); final PsiDocumentManager documentManager = PsiDocumentManager.getInstance(myPsiManager.getProject()); final Document document = viewProvider.getDocument(); final CodeFormatterFacade codeFormatter = new CodeFormatterFacade(styleSettings); documentManager.commitDocument(document); return codeFormatter; }
@Override @NotNull public PsiFile[] getPsiRoots() { final FileViewProvider viewProvider = getViewProvider(); final Set<Language> languages = viewProvider.getLanguages(); final PsiFile[] roots = new PsiFile[languages.size()]; int i = 0; for (Language language : languages) { PsiFile psi = viewProvider.getPsi(language); if (psi == null) { LOG.error("PSI is null for " + language + "; in file: " + this); } roots[i++] = psi; } if (roots.length > 1) { Arrays.sort(roots, FILE_BY_LANGUAGE_ID); } return roots; }
public void beforeDocumentChanged(@NotNull FileViewProvider viewProvider) { if (isViewProviderLocked(viewProvider)) { Throwable cause = viewProvider.getUserData(REFORMAT_ORIGINATOR); @NonNls String message = "Document is locked by write PSI operations. " + "Use PsiDocumentManager.doPostponedOperationsAndUnblockDocument() to commit PSI changes to the document." + (cause == null ? "" : " See cause stacktrace for the reason to lock."); throw cause == null ? new RuntimeException(message) : new RuntimeException(message, cause); } postponedFormatting(viewProvider); }
@NotNull public static PsiFileImpl getFileCopy( @NotNull PsiFileImpl originalFile, @NotNull FileViewProvider providerCopy) { FileViewProvider viewProvider = originalFile.getViewProvider(); Language language = originalFile.getLanguage(); PsiFile file = providerCopy.getPsi(language); if (file != null && !(file instanceof PsiFileImpl)) { throw new RuntimeException( "View provider " + viewProvider + " refused to provide PsiFileImpl for " + language + details(providerCopy, viewProvider)); } PsiFileImpl newFile = (PsiFileImpl) file; if (newFile == null && language == PlainTextLanguage.INSTANCE && originalFile == viewProvider.getPsi(viewProvider.getBaseLanguage())) { newFile = (PsiFileImpl) providerCopy.getPsi(providerCopy.getBaseLanguage()); } if (newFile == null) { throw new RuntimeException( "View provider " + viewProvider + " refused to parse text with " + language + details(providerCopy, viewProvider)); } return newFile; }
protected void reportStubAstMismatch(String message, StubTree stubTree, Document cachedDocument) { rebuildStub(); clearStub("stub-psi mismatch"); scheduleDropCachesWithInvalidStubPsi(); String msg = message; msg += "\n file=" + this; msg += ", modStamp=" + getModificationStamp(); msg += "\n stub debugInfo=" + stubTree.getDebugInfo(); msg += "\n document before=" + cachedDocument; ObjectStubTree latestIndexedStub = StubTreeLoader.getInstance().readFromVFile(getProject(), getVirtualFile()); msg += "\nlatestIndexedStub=" + latestIndexedStub; if (latestIndexedStub != null) { msg += "\n same size=" + (stubTree.getPlainList().size() == latestIndexedStub.getPlainList().size()); msg += "\n debugInfo=" + latestIndexedStub.getDebugInfo(); } FileViewProvider viewProvider = getViewProvider(); msg += "\n viewProvider=" + viewProvider; msg += "\n viewProvider stamp: " + viewProvider.getModificationStamp(); VirtualFile file = viewProvider.getVirtualFile(); msg += "; file stamp: " + file.getModificationStamp(); msg += "; file modCount: " + file.getModificationCount(); Document document = FileDocumentManager.getInstance().getCachedDocument(file); if (document != null) { msg += "\n doc saved: " + !FileDocumentManager.getInstance().isDocumentUnsaved(document); msg += "; doc stamp: " + document.getModificationStamp(); msg += "; doc size: " + document.getTextLength(); msg += "; committed: " + PsiDocumentManager.getInstance(getProject()).isCommitted(document); } throw new AssertionError(msg + "\n------------\n"); }
private static String details(FileViewProvider providerCopy, FileViewProvider viewProvider) { return "; languages: " + viewProvider.getLanguages() + "; base: " + viewProvider.getBaseLanguage() + "; copy: " + providerCopy + "; copy.base: " + providerCopy.getBaseLanguage() + "; vFile: " + viewProvider.getVirtualFile() + "; copy.vFile: " + providerCopy.getVirtualFile() + "; fileType: " + viewProvider.getVirtualFile().getFileType() + "; copy.original(): " + (providerCopy.getVirtualFile() instanceof LightVirtualFile ? ((LightVirtualFile) providerCopy.getVirtualFile()).getOriginalFile() : null); }
public void unloadContent() { ApplicationManager.getApplication().assertWriteAccessAllowed(); clearCaches(); myViewProvider.beforeContentsSynchronized(); synchronized (PsiLock.LOCK) { FileElement treeElement = derefTreeElement(); DebugUtil.startPsiModification("unloadContent"); try { if (treeElement != null) { myTreeElementPointer = null; treeElement.detachFromFile(); DebugUtil.onInvalidated(treeElement); } clearStub("unloadContent"); } finally { DebugUtil.finishPsiModification(); } } }
private void postponeFormatting(@NotNull FileViewProvider viewProvider, @NotNull ASTNode child) { if (!CodeEditUtil.isNodeGenerated(child) && child.getElementType() != TokenType.WHITE_SPACE) { final int oldIndent = CodeEditUtil.getOldIndentation(child); LOG.assertTrue( oldIndent >= 0, "for not generated items old indentation must be defined: element=" + child + ", text=" + child.getText()); } List<ASTNode> list = myReformatElements.get(viewProvider); if (list == null) { list = new ArrayList<ASTNode>(); myReformatElements.put(viewProvider, list); if (STORE_REFORMAT_ORIGINATOR_STACKTRACE) { viewProvider.putUserData(REFORMAT_ORIGINATOR, new Throwable()); } } list.add(child); }