private void reparseParallelTrees(PsiFile changedFile) { List<PsiFile> allFiles = changedFile.getViewProvider().getAllFiles(); if (allFiles.size() <= 1) { return; } CharSequence newText = changedFile.getNode().getChars(); for (final PsiFile file : allFiles) { if (file != changedFile) { FileElement fileElement = ((PsiFileImpl)file).getTreeElement(); if (fileElement != null) { reparseFile(file, fileElement, newText); } } } }
private void reparseFile(final PsiFile file, FileElement treeElement, CharSequence newText) { PsiToDocumentSynchronizer synchronizer =((PsiDocumentManagerBase)PsiDocumentManager.getInstance(myProject)).getSynchronizer(); TextRange changedPsiRange = DocumentCommitProcessor.getChangedPsiRange(file, treeElement, newText); if (changedPsiRange == null) return; final DiffLog log = BlockSupport.getInstance(myProject).reparseRange(file, changedPsiRange, newText, new EmptyProgressIndicator(), treeElement.getText()); synchronizer.setIgnorePsiEvents(true); try { CodeStyleManager.getInstance(file.getProject()).performActionWithFormatterDisabled(new Runnable() { @Override public void run() { runTransaction(new PomTransactionBase(file, getModelAspect(TreeAspect.class)) { @Nullable @Override public PomModelEvent runInner() throws IncorrectOperationException { return new TreeAspectEvent(PomModelImpl.this, log.performActualPsiChange(file)); } }); } }); } finally { synchronizer.setIgnorePsiEvents(false); } }
@Nullable private static PsiFile getContainingFileByTree(@NotNull final PsiElement changeScope) { // there could be pseudo physical trees (JSPX/JSP/etc.) which must not translate // any changes to document and not to fire any PSI events final PsiFile psiFile; final ASTNode node = changeScope.getNode(); if (node == null) { psiFile = changeScope.getContainingFile(); } else { final FileElement fileElement = TreeUtil.getFileElement((TreeElement)node); // assert fileElement != null : "Can't find file element for node: " + node; // Hack. the containing tree can be invalidated if updating supplementary trees like HTML in JSP. if (fileElement == null) return null; psiFile = (PsiFile)fileElement.getPsi(); } return psiFile.getNode() != null ? psiFile : null; }
/** * Ensures this element is AST-based. This is an expensive operation that might take significant time and allocate lots of objects, * so it should be to be avoided if possible. * * @return an AST node corresponding to this element. If the element is currently operating via stubs, * this causes AST to be loaded for the whole file and all stub-based PSI elements in this file (including the current one) * to be switched from stub to AST. So, after this call {@link #getStub()} will return null. */ @Override @NotNull public ASTNode getNode() { ASTNode node = myNode; if (node == null) { ApplicationManager.getApplication().assertReadAccessAllowed(); PsiFileImpl file = (PsiFileImpl)getContainingFile(); if (!file.isValid()) throw new PsiInvalidElementAccessException(this); FileElement treeElement = file.getTreeElement(); if (treeElement != null && myNode == null) { return notBoundInExistingAst(file, treeElement); } treeElement = file.calcTreeElement(); node = myNode; if (node == null) { return failedToBindStubToAst(file, treeElement); } } return node; }
private ASTNode failedToBindStubToAst(PsiFileImpl file, FileElement fileElement) { VirtualFile vFile = file.getVirtualFile(); StubTree stubTree = file.getStubTree(); String stubString = stubTree != null ? ((PsiFileStubImpl)stubTree.getRoot()).printTree() : "is null"; String astString = DebugUtil.treeToString(fileElement, true); if (!ourTraceStubAstBinding) { stubString = StringUtil.trimLog(stubString, 1024); astString = StringUtil.trimLog(astString, 1024); } @NonNls String message = "Failed to bind stub to AST for element " + getClass() + " in " + (vFile == null ? "<unknown file>" : vFile.getPath()) + "\nFile:\n" + file + "@" + System.identityHashCode(file) + "\nFile stub tree:\n" + stubString + "\nLoaded file AST:\n" + astString; if (ourTraceStubAstBinding) { message += dumpCreationTraces(fileElement); } throw new IllegalArgumentException(message); }
private String dumpCreationTraces(FileElement fileElement) { final StringBuilder traces = new StringBuilder("\nNow " + Thread.currentThread() + "\n"); traces.append("My creation trace:\n").append(getUserData(CREATION_TRACE)); traces.append("AST creation traces:\n"); fileElement.acceptTree(new RecursiveTreeElementWalkingVisitor(false) { @Override public void visitComposite(CompositeElement composite) { PsiElement psi = composite.getPsi(); if (psi != null) { traces.append(psi).append("@").append(System.identityHashCode(psi)).append("\n"); String trace = psi.getUserData(CREATION_TRACE); if (trace != null) { traces.append(trace).append("\n"); } } super.visitComposite(composite); } }); return traces.toString(); }
private ASTNode notBoundInExistingAst(PsiFileImpl file, FileElement treeElement) { String message = "file=" + file + "; tree=" + treeElement; PsiElement each = this; while (each != null) { message += "\n each of class " + each.getClass() + "; valid=" + each.isValid(); if (each instanceof StubBasedPsiElementBase) { message += "; node=" + ((StubBasedPsiElementBase)each).myNode + "; stub=" + ((StubBasedPsiElementBase)each).myStub; each = ((StubBasedPsiElementBase)each).getParentByStub(); } else { if (each instanceof PsiFile) { message += "; same file=" + (each == file) + "; current tree= " + file.getTreeElement() + "; stubTree=" + file.getStubTree() + "; physical=" + file.isPhysical(); } break; } } StubElement eachStub = myStub; while (eachStub != null) { message += "\n each stub " + (eachStub instanceof PsiFileStubImpl ? ((PsiFileStubImpl)eachStub).getDiagnostics() : eachStub); eachStub = eachStub.getParentStub(); } if (ourTraceStubAstBinding) { message += dumpCreationTraces(treeElement); } throw new AssertionError(message); }
private void checkLengthConsistency() { Document document = getCachedDocument(); if (document instanceof DocumentWindow) { return; } if (document != null && ((PsiDocumentManagerBase)PsiDocumentManager.getInstance(myManager.getProject())).getSynchronizer().isInSynchronization(document)) { return; } List<FileElement> knownTreeRoots = getKnownTreeRoots(); if (knownTreeRoots.isEmpty()) return; int fileLength = myContent.getTextLength(); for (FileElement fileElement : knownTreeRoots) { int nodeLength = fileElement.getTextLength(); if (nodeLength != fileLength) { // exceptions here should be assigned to peter LOG.error("Inconsistent " + fileElement.getElementType() + " tree in " + this + "; nodeLength=" + nodeLength + "; fileLength=" + fileLength); } } }
private static int getMatchingLength(@NotNull FileElement treeElement, @NotNull CharSequence text, boolean fromStart) { int patternIndex = fromStart ? 0 : text.length() - 1; int finalPatternIndex = fromStart ? text.length() - 1 : 0; int direction = fromStart ? 1 : -1; ASTNode leaf = fromStart ? TreeUtil.findFirstLeaf(treeElement, false) : TreeUtil.findLastLeaf(treeElement, false); int result = 0; while (leaf != null && (fromStart ? patternIndex <= finalPatternIndex : patternIndex >= finalPatternIndex)) { if (!(leaf instanceof ForeignLeafPsiElement)) { CharSequence chars = leaf.getChars(); if (chars.length() > 0) { int matchingLength = getLeafMatchingLength(chars, text, patternIndex, finalPatternIndex, direction); result += matchingLength; if (matchingLength != chars.length()) { break; } patternIndex += (fromStart ? matchingLength : -matchingLength); } } leaf = fromStart ? TreeUtil.nextLeaf(leaf, false) : TreeUtil.prevLeaf(leaf, false); } return result; }
public DummyHolder(@NotNull PsiManager manager, @Nullable TreeElement contentElement, @Nullable PsiElement context, @Nullable CharTable table, @Nullable Boolean validity, Language language) { super(TokenType.DUMMY_HOLDER, TokenType.DUMMY_HOLDER, new DummyHolderViewProvider(manager)); myLanguage = language; ((DummyHolderViewProvider)getViewProvider()).setDummyHolder(this); myContext = context; myTable = table != null ? table : IdentityCharTable.INSTANCE; if (contentElement instanceof FileElement) { myFileElement = (FileElement)contentElement; myFileElement.setPsi(this); myFileElement.setCharTable(myTable); } else if (contentElement != null) { getTreeElement().rawAddChildren(contentElement); clearCaches(); } myExplicitlyValid = validity; }
@Nullable public PsiElement createElementFromText(@Nullable final String text, @NotNull final Language language, @NotNull final IElementType type, @Nullable final PsiElement context) { if (text == null) return null; final DummyHolder result = DummyHolderFactory.createHolder(myManager, language, context); final FileElement holder = result.getTreeElement(); final ParserDefinition parserDefinition = LanguageParserDefinitions.INSTANCE.forLanguage(language); if (parserDefinition == null) { throw new AssertionError("No parser definition for " + language); } final Project project = myManager.getProject(); final Lexer lexer = parserDefinition.createLexer(project); final PsiBuilder builder = PsiBuilderFactory.getInstance().createBuilder(project, holder, lexer, language, text); final ASTNode node = parserDefinition.createParser(project).parse(type, builder); holder.rawAddChildren((TreeElement)node); markGenerated(result); return node.getPsi(); }
@NotNull private static Pair<PsiElement, CharTable> doFindWhiteSpaceNode(@NotNull PsiFile file, int offset) { ASTNode astNode = SourceTreeToPsiMap.psiElementToTree(file); if (!(astNode instanceof FileElement)) { return new Pair<PsiElement, CharTable>(null, null); } PsiElement elementAt = InjectedLanguageUtil.findInjectedElementNoCommit(file, offset); final CharTable charTable = ((FileElement)astNode).getCharTable(); if (elementAt == null) { elementAt = findElementInTreeWithFormatterEnabled(file, offset); } if( elementAt == null) { return new Pair<PsiElement, CharTable>(null, charTable); } ASTNode node = elementAt.getNode(); if (node == null || node.getElementType() != TokenType.WHITE_SPACE) { return new Pair<PsiElement, CharTable>(null, charTable); } return Pair.create(elementAt, charTable); }
private void reparseParallelTrees(PsiFile changedFile) { List<PsiFile> allFiles = changedFile.getViewProvider().getAllFiles(); if (allFiles.size() <= 1) { return; } String newText = changedFile.getNode().getText(); for (final PsiFile file : allFiles) { if (file != changedFile) { FileElement fileElement = ((PsiFileImpl)file).getTreeElement(); if (fileElement != null) { String oldText = fileElement.getText(); try { reparseFile(file, newText, oldText); } finally { TextBlock.get(file).clear(); } } } } }
@Override @NotNull public ASTNode getNode() { ASTNode node = myNode; if (node == null) { ApplicationManager.getApplication().assertReadAccessAllowed(); PsiFileImpl file = (PsiFileImpl)getContainingFile(); if (!file.isValid()) throw new PsiInvalidElementAccessException(this); FileElement treeElement = file.getTreeElement(); StubTree stubTree = file.getStubTree(); if (treeElement != null && myNode == null) { return notBoundInExistingAst(file, treeElement, stubTree); } final FileElement fileElement = file.calcTreeElement(); node = myNode; if (node == null) { return failedToBindStubToAst(file, stubTree, fileElement); } } return node; }
private ASTNode failedToBindStubToAst(PsiFileImpl file, StubTree stubTree, FileElement fileElement) { VirtualFile vFile = file.getVirtualFile(); String stubString = stubTree != null ? ((PsiFileStubImpl)stubTree.getRoot()).printTree() : "is null"; String astString = DebugUtil.treeToString(fileElement, true); if (!ourTraceStubAstBinding) { stubString = StringUtil.trimLog(stubString, 1024); astString = StringUtil.trimLog(astString, 1024); } @NonNls String message = "Failed to bind stub to AST for element " + getClass() + " in " + (vFile == null ? "<unknown file>" : vFile.getPath()) + "\nFile:\n" + file.toString() + "@" + System.identityHashCode(file) + "\nFile stub tree:\n" + stubString + "\nLoaded file AST:\n" + astString; if (ourTraceStubAstBinding) { message += dumpCreationTraces(fileElement); } throw new IllegalArgumentException(message); }
private String dumpCreationTraces(FileElement fileElement) { final StringBuilder traces = new StringBuilder("\nNow " + Thread.currentThread() + "\n"); traces.append("My creation trace:\n").append(getUserData(CREATION_TRACE)); traces.append("AST creation traces:\n"); fileElement.acceptTree(new RecursiveTreeElementWalkingVisitor(false) { @Override public void visitComposite(CompositeElement composite) { PsiElement psi = composite.getPsi(); if (psi != null) { traces.append(psi.toString()).append("@").append(System.identityHashCode(psi)).append("\n"); String trace = psi.getUserData(CREATION_TRACE); if (trace != null) { traces.append(trace).append("\n"); } } super.visitComposite(composite); } }); return traces.toString(); }
private ASTNode notBoundInExistingAst(PsiFileImpl file, FileElement treeElement, StubTree stubTree) { @NonNls String message = "this=" + this.getClass() + "; file.isPhysical=" + file.isPhysical() + "; node=" + myNode + "; file=" + file + "; tree=" + treeElement + "; stubTree=" + stubTree; PsiElement each = this; while (each != null) { message += "\n each of class " + each.getClass(); if (each instanceof StubBasedPsiElementBase) { message += "; node=" + ((StubBasedPsiElementBase)each).myNode + "; stub=" + ((StubBasedPsiElementBase)each).myStub; each = ((StubBasedPsiElementBase)each).getParentByStub(); } else { break; } } if (ourTraceStubAstBinding) { message += dumpCreationTraces(treeElement); } throw new AssertionError(message); }
private void reparseParallelTrees(PsiFile changedFile, PsiToDocumentSynchronizer synchronizer) { List<PsiFile> allFiles = changedFile.getViewProvider().getAllFiles(); if (allFiles.size() <= 1) { return; } CharSequence newText = changedFile.getNode().getChars(); for (final PsiFile file : allFiles) { FileElement fileElement = file == changedFile ? null : ((PsiFileImpl)file).getTreeElement(); Runnable changeAction = fileElement == null ? null : reparseFile(file, fileElement, newText); if (changeAction == null) continue; synchronizer.setIgnorePsiEvents(true); try { CodeStyleManager.getInstance(file.getProject()).performActionWithFormatterDisabled(changeAction); } finally { synchronizer.setIgnorePsiEvents(false); } } }
@Nullable private Runnable reparseFile(@Nonnull final PsiFile file, @Nonnull FileElement treeElement, @Nonnull CharSequence newText) { TextRange changedPsiRange = ChangedPsiRangeUtil.getChangedPsiRange(file, treeElement, newText); if (changedPsiRange == null) return null; Runnable reparseLeaf = tryReparseOneLeaf(treeElement, newText, changedPsiRange); if (reparseLeaf != null) return reparseLeaf; final DiffLog log = BlockSupport.getInstance(myProject).reparseRange(file, treeElement, changedPsiRange, newText, new EmptyProgressIndicator(), treeElement.getText()); return () -> runTransaction(new PomTransactionBase(file, getModelAspect(TreeAspect.class)) { @Override public PomModelEvent runInner() throws IncorrectOperationException { return new TreeAspectEvent(PomModelImpl.this, log.performActualPsiChange(file)); } }); }
@Nullable private static PsiFile getContainingFileByTree(@Nonnull final PsiElement changeScope) { // there could be pseudo physical trees (JSPX/JSP/etc.) which must not translate // any changes to document and not to fire any PSI events final PsiFile psiFile; final ASTNode node = changeScope.getNode(); if (node == null) { psiFile = changeScope.getContainingFile(); } else { final FileElement fileElement = TreeUtil.getFileElement((TreeElement)node); // assert fileElement != null : "Can't find file element for node: " + node; // Hack. the containing tree can be invalidated if updating supplementary trees like HTML in JSP. if (fileElement == null) return null; psiFile = (PsiFile)fileElement.getPsi(); } return psiFile.getNode() != null ? psiFile : null; }
/** * Ensures this element is AST-based. This is an expensive operation that might take significant time and allocate lots of objects, * so it should be to be avoided if possible. * * @return an AST node corresponding to this element. If the element is currently operating via stubs, * this causes AST to be loaded for the whole file and all stub-based PSI elements in this file (including the current one) * to be switched from stub to AST. So, after this call {@link #getStub()} will return null. */ @Override @Nonnull public ASTNode getNode() { if (mySubstrateRef instanceof SubstrateRef.StubRef) { ApplicationManager.getApplication().assertReadAccessAllowed(); PsiFileImpl file = (PsiFileImpl)getContainingFile(); if (!file.isValid()) throw new PsiInvalidElementAccessException(this); FileElement treeElement = file.getTreeElement(); if (treeElement != null && mySubstrateRef instanceof SubstrateRef.StubRef) { return notBoundInExistingAst(file, treeElement); } treeElement = file.calcTreeElement(); if (mySubstrateRef instanceof SubstrateRef.StubRef) { return failedToBindStubToAst(file, treeElement); } } return mySubstrateRef.getNode(); }
private ASTNode failedToBindStubToAst(@Nonnull PsiFileImpl file, @Nonnull final FileElement fileElement) { VirtualFile vFile = file.getVirtualFile(); StubTree stubTree = file.getStubTree(); final String stubString = stubTree != null ? ((PsiFileStubImpl)stubTree.getRoot()).printTree() : null; final String astString = RecursionManager.doPreventingRecursion("failedToBindStubToAst", true, () -> DebugUtil.treeToString(fileElement, true)); @NonNls final String message = "Failed to bind stub to AST for element " + getClass() + " in " + (vFile == null ? "<unknown file>" : vFile.getPath()) + "\nFile:\n" + file + "@" + System.identityHashCode(file); final String creationTraces = ourTraceStubAstBinding ? dumpCreationTraces(fileElement) : null; List<Attachment> attachments = new ArrayList<>(); if (stubString != null) { attachments.add(new Attachment("stubTree.txt", stubString)); } if (astString != null) { attachments.add(new Attachment("ast.txt", astString)); } if (creationTraces != null) { attachments.add(new Attachment("creationTraces.txt", creationTraces)); } throw new RuntimeExceptionWithAttachments(message, attachments.toArray(Attachment.EMPTY_ARRAY)); }
@Nonnull private String dumpCreationTraces(@Nonnull FileElement fileElement) { final StringBuilder traces = new StringBuilder("\nNow " + Thread.currentThread() + "\n"); traces.append("My creation trace:\n").append(getUserData(CREATION_TRACE)); traces.append("AST creation traces:\n"); fileElement.acceptTree(new RecursiveTreeElementWalkingVisitor(false) { @Override public void visitComposite(CompositeElement composite) { PsiElement psi = composite.getPsi(); if (psi != null) { traces.append(psi).append("@").append(System.identityHashCode(psi)).append("\n"); String trace = psi.getUserData(CREATION_TRACE); if (trace != null) { traces.append(trace).append("\n"); } } super.visitComposite(composite); } }); return traces.toString(); }
@SuppressWarnings("AssignmentToStaticFieldFromInstanceMethod") public void reparseFileFromText(@Nonnull PsiFileImpl file) { ApplicationManager.getApplication().assertIsDispatchThread(); if (isCommitInProgress()) throw new IllegalStateException("Re-entrant commit is not allowed"); FileElement node = file.calcTreeElement(); CharSequence text = node.getChars(); ourIsFullReparseInProgress = true; try { WriteAction.run(() -> { ProgressIndicator indicator = ProgressIndicatorProvider.getGlobalProgressIndicator(); if (indicator == null) indicator = new EmptyProgressIndicator(); DiffLog log = BlockSupportImpl.makeFullParse(file, node, text, indicator, text).getFirst(); log.doActualPsiChange(file); file.getViewProvider().contentsSynchronized(); }); } finally { ourIsFullReparseInProgress = false; } }
public DummyHolder(@Nonnull PsiManager manager, @Nullable TreeElement contentElement, @Nullable PsiElement context, @Nullable CharTable table, @Nullable Boolean validity, Language language) { super(TokenType.DUMMY_HOLDER, TokenType.DUMMY_HOLDER, new DummyHolderViewProvider(manager)); myLanguage = language; ((DummyHolderViewProvider)getViewProvider()).setDummyHolder(this); myContext = context; myTable = table != null ? table : IdentityCharTable.INSTANCE; if (contentElement instanceof FileElement) { ((FileElement)contentElement).setPsi(this); ((FileElement)contentElement).setCharTable(myTable); setTreeElementPointer((FileElement)contentElement); } else if (contentElement != null) { getTreeElement().rawAddChildren(contentElement); clearCaches(); } myExplicitlyValid = validity; }
private static int getMatchingLength(@Nonnull FileElement treeElement, @Nonnull CharSequence text, boolean fromStart) { int patternIndex = fromStart ? 0 : text.length() - 1; int finalPatternIndex = fromStart ? text.length() - 1 : 0; int direction = fromStart ? 1 : -1; ASTNode leaf = fromStart ? TreeUtil.findFirstLeaf(treeElement, false) : TreeUtil.findLastLeaf(treeElement, false); int result = 0; while (leaf != null && (fromStart ? patternIndex <= finalPatternIndex : patternIndex >= finalPatternIndex)) { if (!(leaf instanceof ForeignLeafPsiElement)) { CharSequence chars = leaf.getChars(); if (chars.length() > 0) { int matchingLength = getLeafMatchingLength(chars, text, patternIndex, finalPatternIndex, direction); result += matchingLength; if (matchingLength != chars.length()) { break; } patternIndex += fromStart ? matchingLength : -matchingLength; } } leaf = fromStart ? TreeUtil.nextLeaf(leaf, false) : TreeUtil.prevLeaf(leaf, false); } return result; }
@Nullable public PsiElement createElementFromText(@Nullable final String text, @Nonnull final Language language, @Nonnull final LanguageVersion languageVersion, @Nonnull final IElementType type, @Nullable final PsiElement context) { if (text == null) return null; final DummyHolder result = DummyHolderFactory.createHolder(myManager, language, context); final FileElement holder = result.getTreeElement(); final ParserDefinition parserDefinition = LanguageParserDefinitions.INSTANCE.forLanguage(language); if (parserDefinition == null) { throw new AssertionError("No parser definition for " + language); } final Project project = myManager.getProject(); final Lexer lexer = parserDefinition.createLexer(languageVersion); final PsiBuilder builder = PsiBuilderFactory.getInstance().createBuilder(project, holder, lexer, language, languageVersion, text); final ASTNode node = parserDefinition.createParser(languageVersion).parse(type, builder, languageVersion); holder.rawAddChildren((TreeElement)node); markGenerated(result); return node.getPsi(); }
@Nonnull private static Pair<PsiElement, CharTable> doFindWhiteSpaceNode(@Nonnull PsiFile file, int offset) { ASTNode astNode = SourceTreeToPsiMap.psiElementToTree(file); if (!(astNode instanceof FileElement)) { return new Pair<>(null, null); } PsiElement elementAt = InjectedLanguageManager.getInstance(file.getProject()).findInjectedElementAt(file, offset); final CharTable charTable = ((FileElement)astNode).getCharTable(); if (elementAt == null) { elementAt = findElementInTreeWithFormatterEnabled(file, offset); } if( elementAt == null) { return new Pair<>(null, charTable); } ASTNode node = elementAt.getNode(); if (node == null || node.getElementType() != TokenType.WHITE_SPACE) { return new Pair<>(null, charTable); } return Pair.create(elementAt, charTable); }
protected PsiElement createEmptyPsiField() { final String text = "<undefined>"; final IElementType type = CsvTypes.FIELD; final Project project = this.element.getProject(); final PsiManager psiManager = PsiManager.getInstance(project); final DummyHolder dummyHolder = DummyHolderFactory.createHolder(psiManager, null); final FileElement fileElement = dummyHolder.getTreeElement(); final ParserDefinition parserDefinition = LanguageParserDefinitions.INSTANCE.forLanguage(CsvLanguage.INSTANCE); final Lexer lexer = parserDefinition.createLexer(project); final PsiBuilder psiBuilder = PsiBuilderFactory.getInstance().createBuilder(project, fileElement, lexer, CsvLanguage.INSTANCE, text); final ASTNode node = parserDefinition.createParser(project).parse(type, psiBuilder); fileElement.rawAddChildren((com.intellij.psi.impl.source.tree.TreeElement)node); return node.getPsi(); }
@Override public boolean isCollapsedByDefault(@NotNull ASTNode node) { // This code should collapse header comments. // However, in most of the cases it will not work, // as when file is open caret is at the beginning of the document, // thus preventing collapsing it. // TODO: Collapse header comment when file is opened return node.getTreeParent() instanceof FileElement && findPreviousNonWhitespaceOrCommentNode(node) == null; }
private static IncorrectOperationException newException(final String msg, final DummyHolder holder) { final FileElement root = holder.getTreeElement(); if (root instanceof JavaDummyElement) { final Throwable cause = ((JavaDummyElement)root).getParserError(); if (cause != null) { return new IncorrectOperationException(msg, cause); } } return new IncorrectOperationException(msg); }
@Override @NotNull public FormattingModel createModel(final PsiElement element, final CodeStyleSettings settings) { final FileElement fileElement = TreeUtil.getFileElement((TreeElement)SourceTreeToPsiMap.psiElementToTree(element)); LOG.assertTrue(fileElement != null, "File element should not be null for " + element); CommonCodeStyleSettings commonSettings = settings.getCommonSettings(JavaLanguage.INSTANCE); JavaCodeStyleSettings customJavaSettings = settings.getCustomSettings(JavaCodeStyleSettings.class); Block block = AbstractJavaBlock.newJavaBlock(fileElement, commonSettings, customJavaSettings); FormattingDocumentModelImpl model = FormattingDocumentModelImpl.createOn(element.getContainingFile()); return new PsiBasedFormatterModelWithShiftIndentInside (element.getContainingFile(), block, model); }
private long collectAndCheckHighlighting(@NotNull ExpectedHighlightingData data) { final Project project = getProject(); PsiDocumentManager.getInstance(project).commitAllDocuments(); PsiFileImpl file = (PsiFileImpl)getHostFile(); FileElement hardRefToFileElement = file.calcTreeElement();//to load text //to initialize caches if (!DumbService.isDumb(project)) { CacheManager.SERVICE.getInstance(project).getFilesWithWord("XXX", UsageSearchContext.IN_COMMENTS, GlobalSearchScope.allScope(project), true); } final long start = System.currentTimeMillis(); final VirtualFileFilter fileTreeAccessFilter = myVirtualFileFilter; Disposable disposable = Disposer.newDisposable(); if (fileTreeAccessFilter != null) { ((PsiManagerImpl)PsiManager.getInstance(project)).setAssertOnFileLoadingFilter(fileTreeAccessFilter, disposable); } // ProfilingUtil.startCPUProfiling(); List<HighlightInfo> infos; try { infos = doHighlighting(); removeDuplicatedRangesForInjected(infos); } finally { Disposer.dispose(disposable); } // ProfilingUtil.captureCPUSnapshot("testing"); final long elapsed = System.currentTimeMillis() - start; data.checkResult(infos, file.getText()); hardRefToFileElement.hashCode(); // use it so gc won't collect it return elapsed; }
@NotNull @Override public List<FileElement> getKnownTreeRoots() { List<FileElement> files = new ArrayList<FileElement>(myRoots.size()); for (PsiFile file : myRoots.values()) { final FileElement treeElement = ((PsiFileImpl)file).getTreeElement(); if (treeElement != null) { files.add(treeElement); } } return files; }
@NotNull public List<FileElement> getKnownTreeRoots() { PsiFile psiFile = getCachedPsi(myBaseLanguage); if (!(psiFile instanceof PsiFileImpl)) return Collections.emptyList(); FileElement element = ((PsiFileImpl)psiFile).getTreeElement(); return ContainerUtil.createMaybeSingletonList(element); }
@Nullable public static TextRange getChangedPsiRange(@NotNull PsiFile file, @NotNull FileElement treeElement, @NotNull CharSequence newDocumentText) { int psiLength = treeElement.getTextLength(); if (!file.getViewProvider().supportsIncrementalReparse(file.getLanguage())) { return new TextRange(0, psiLength); } int commonPrefixLength = getMatchingLength(treeElement, newDocumentText, true); if (commonPrefixLength == newDocumentText.length() && newDocumentText.length() == psiLength) { return null; } int commonSuffixLength = Math.min(getMatchingLength(treeElement, newDocumentText, false), psiLength - commonPrefixLength); return new TextRange(commonPrefixLength, psiLength - commonSuffixLength); }
private void assertAfterCommit(@NotNull Document document, @NotNull final PsiFile file, @NotNull FileElement myTreeElementBeingReparsedSoItWontBeCollected) { if (myTreeElementBeingReparsedSoItWontBeCollected.getTextLength() != document.getTextLength()) { final String documentText = document.getText(); String fileText = file.getText(); LOG.error("commitDocument left PSI inconsistent: " + file + "; file len=" + myTreeElementBeingReparsedSoItWontBeCollected.getTextLength() + "; doc len=" + document.getTextLength() + "; doc.getText() == file.getText(): " + Comparing.equal(fileText, documentText), new Attachment("file psi text", fileText), new Attachment("old text", documentText)); file.putUserData(BlockSupport.DO_NOT_REPARSE_INCREMENTALLY, Boolean.TRUE); try { BlockSupport blockSupport = BlockSupport.getInstance(file.getProject()); final DiffLog diffLog = blockSupport.reparseRange(file, new TextRange(0, documentText.length()), documentText, createProgressIndicator(), myTreeElementBeingReparsedSoItWontBeCollected.getText()); doActualPsiChange(file, diffLog); if (myTreeElementBeingReparsedSoItWontBeCollected.getTextLength() != document.getTextLength()) { LOG.error("PSI is broken beyond repair in: " + file); } } finally { file.putUserData(BlockSupport.DO_NOT_REPARSE_INCREMENTALLY, null); } } }