protected void doReparse(final String s, final int length) { CommandProcessor.getInstance().executeCommand(getProject(), new Runnable() { @Override public void run() { ApplicationManager.getApplication().runWriteAction(new Runnable() { @Override public void run() { BlockSupport blockSupport = ServiceManager.getService(myProject, BlockSupport.class); try { blockSupport.reparseRange(myDummyFile, myInsertOffset - length, myInsertOffset, s); } catch (IncorrectOperationException e) { LOG.error(e); } } }); } }, "asd", null); }
public void testMergeWhenEmptyElementAfterWhitespaceIsLastChild() throws Throwable { myBuilder = createBuilder(" foo bar"); parseWhenEmptyElementAfterWhitespaceIsLastChild(); final ASTNode tree = myBuilder.getTreeBuilt(); new DummyHolder(getPsiManager(), (TreeElement)tree, null); myBuilder = createBuilder(" bar", tree); parseWhenEmptyElementAfterWhitespaceIsLastChild(); DebugUtil.startPsiModification(null); try { myBuilder.getTreeBuilt(); fail(); } catch (BlockSupport.ReparsedSuccessfullyException e) { e.getDiffLog().performActualPsiChange(tree.getPsi().getContainingFile()); } finally { DebugUtil.finishPsiModification(); } assertEquals(" bar", tree.getText()); }
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); } }
@NotNull private ASTNode buildTree() { final StartMarker rootMarker = prepareLightTree(); final boolean isTooDeep = myFile != null && BlockSupport.isTooDeep(myFile.getOriginalFile()); if (myOriginalTree != null && !isTooDeep) { DiffLog diffLog = merge(myOriginalTree, rootMarker, myLastCommittedText); throw new BlockSupport.ReparsedSuccessfullyException(diffLog); } final ASTNode rootNode = createRootAST(rootMarker); bind(rootMarker, (CompositeElement)rootNode); if (isTooDeep && !(rootNode instanceof FileElement)) { final ASTNode childNode = rootNode.getFirstChildNode(); childNode.putUserData(BlockSupport.TREE_DEPTH_LIMIT_EXCEEDED, Boolean.TRUE); } return rootNode; }
public void testMergeWhenEmptyElementAfterWhitespaceIsLastChild() throws Throwable { myBuilder = createBuilder(" foo bar"); parseWhenEmptyElementAfterWhitespaceIsLastChild(); final ASTNode tree = myBuilder.getTreeBuilt(); new DummyHolder(getPsiManager(), (TreeElement)tree, null); myBuilder = createBuilder(" bar", tree); parseWhenEmptyElementAfterWhitespaceIsLastChild(); try { myBuilder.getTreeBuilt(); fail(); } catch (BlockSupport.ReparsedSuccessfullyException e) { e.getDiffLog().performActualPsiChange(tree.getPsi().getContainingFile()); } assertEquals(" bar", tree.getText()); }
private ASTNode buildTree() { final StartMarker rootMarker = prepareLightTree(); final boolean isTooDeep = myFile != null && BlockSupport.isTooDeep(myFile.getOriginalFile()); if (myOriginalTree != null && !isTooDeep) { DiffLog diffLog = merge(myOriginalTree, rootMarker); throw new BlockSupport.ReparsedSuccessfullyException(diffLog); } final ASTNode rootNode = createRootAST(rootMarker); bind(rootMarker, (CompositeElement)rootNode); if (isTooDeep && !(rootNode instanceof FileElement)) { final ASTNode childNode = rootNode.getFirstChildNode(); childNode.putUserData(BlockSupport.TREE_DEPTH_LIMIT_EXCEEDED, Boolean.TRUE); } return rootNode; }
@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)); } }); }
protected void doReparse(final String s, final int length) { CommandProcessor.getInstance().executeCommand(getProject(), new Runnable() { @Override public void run() { ApplicationManager.getApplication().runWriteAction(new Runnable() { @Override public void run() { BlockSupport blockSupport = ServiceManager.getService(myProject, BlockSupport.class); try { blockSupport.reparseRange(myDummyFile, myInsertOffset - length, myInsertOffset, s); } catch(IncorrectOperationException e) { LOGGER.error(e); } } }); } }, "asd", null); }
@Nullable public static String[] getNames(final ExpressionContext context) { final Project project = context.getProject(); final int offset = context.getStartOffset(); PsiDocumentManager.getInstance(project).commitAllDocuments(); String[] names = null; PsiFile file = PsiDocumentManager.getInstance(project).getPsiFile(context.getEditor().getDocument()); PsiElement element = file.findElementAt(offset); if (element instanceof PsiIdentifier){ names = getNamesForIdentifier(project, (PsiIdentifier)element); } else{ final PsiFile fileCopy = (PsiFile)file.copy(); ApplicationManager.getApplication().runWriteAction(new Runnable() { @Override public void run() { BlockSupport blockSupport = BlockSupport.getInstance(project); try{ blockSupport.reparseRange(fileCopy, offset, offset, "xxx"); } catch(IncorrectOperationException e){ LOG.error(e); } } }); PsiElement identifierCopy = fileCopy.findElementAt(offset); if (identifierCopy instanceof PsiIdentifier) { names = getNamesForIdentifier(project, (PsiIdentifier)identifierCopy); } } return names; }
public PsiBuilderImpl(@NotNull final Project project, @NotNull final ParserDefinition parserDefinition, @NotNull final Lexer lexer, @NotNull final ASTNode chameleon, @NotNull final CharSequence text) { this(project, SharedImplUtil.getContainingFile(chameleon), parserDefinition.getWhitespaceTokens(), parserDefinition.getCommentTokens(), lexer, SharedImplUtil.findCharTableByTree(chameleon), text, Pair.getFirst(chameleon.getUserData(BlockSupport.TREE_TO_BE_REPARSED)), Pair.getSecond(chameleon.getUserData(BlockSupport.TREE_TO_BE_REPARSED)), null, null); }
private void checkTreeDepth(final int maxDepth, final boolean isFileRoot) { if (myFile == null) return; final PsiFile file = myFile.getOriginalFile(); final Boolean flag = file.getUserData(BlockSupport.TREE_DEPTH_LIMIT_EXCEEDED); if (maxDepth > BlockSupport.INCREMENTAL_REPARSE_DEPTH_LIMIT) { if (!Boolean.TRUE.equals(flag)) { file.putUserData(BlockSupport.TREE_DEPTH_LIMIT_EXCEEDED, Boolean.TRUE); } } else if (isFileRoot && flag != null) { file.putUserData(BlockSupport.TREE_DEPTH_LIMIT_EXCEEDED, null); } }
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); } } }
@Override @NotNull public ASTNode parse(@NotNull IElementType root, @NotNull PsiBuilder builder) { try { parseLight(root, builder); return builder.getTreeBuilt(); } catch (ProcessCanceledException | BlockSupport.ReparsedSuccessfullyException ignore) { // Not a problem throw ignore; } catch (Exception ex) { crashing = true; Logger.getLogger("GLSLParser").log(Level.WARNING, "Crashed while trying to parse "+root, ex); throw ex; } }
private void reparseFile(final PsiFile file, String newText, String oldText) { if (oldText.equals(newText)) return; PsiToDocumentSynchronizer synchronizer =((PsiDocumentManagerBase)PsiDocumentManager.getInstance(myProject)).getSynchronizer(); int changeStart = StringUtil.commonPrefixLength(oldText, newText); int changeEnd = oldText.length() - StringUtil.commonSuffixLength(oldText, newText); TextRange changedPsiRange = DocumentCommitProcessor.getChangedPsiRange(file, changeStart, changeEnd, newText.length()); final DiffLog log = BlockSupport.getInstance(myProject).reparseRange(file, changedPsiRange, newText, new EmptyProgressIndicator()); 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); } }
public PsiBuilderImpl(@NotNull final Project project, @NotNull final ParserDefinition parserDefinition, @NotNull final Lexer lexer, @NotNull final ASTNode chameleon, @NotNull final CharSequence text) { this(project, SharedImplUtil.getContainingFile(chameleon), parserDefinition, lexer, SharedImplUtil.findCharTableByTree(chameleon), text, chameleon.getUserData(BlockSupport.TREE_TO_BE_REPARSED), null); }
public PsiBuilderImpl(@Nonnull Project project, @Nonnull ParserDefinition parserDefinition, @Nonnull LanguageVersion languageVersion, @Nonnull Lexer lexer, @Nonnull ASTNode chameleon, @Nonnull CharSequence text) { this(project, SharedImplUtil.getContainingFile(chameleon), languageVersion, parserDefinition, lexer, SharedImplUtil.findCharTableByTree(chameleon), text, Pair.getFirst(chameleon.getUserData(BlockSupport.TREE_TO_BE_REPARSED)), Pair.getSecond(chameleon.getUserData(BlockSupport.TREE_TO_BE_REPARSED)), null, chameleon); }
private static void assertAfterCommit(@Nonnull Document document, @Nonnull final PsiFile file, @Nonnull FileElement oldFileNode) { if (oldFileNode.getTextLength() != document.getTextLength()) { final String documentText = document.getText(); String fileText = file.getText(); boolean sameText = Comparing.equal(fileText, documentText); LOG.error("commitDocument() left PSI inconsistent: " + DebugUtil.diagnosePsiDocumentInconsistency(file, document) + "; node.length=" + oldFileNode.getTextLength() + "; doc.text" + (sameText ? "==" : "!=") + "file.text" + "; file name:" + file.getName() + "; type:" + file.getFileType() + "; lang:" + file.getLanguage()); file.putUserData(BlockSupport.DO_NOT_REPARSE_INCREMENTALLY, Boolean.TRUE); try { BlockSupport blockSupport = BlockSupport.getInstance(file.getProject()); final DiffLog diffLog = blockSupport.reparseRange(file, file.getNode(), new TextRange(0, documentText.length()), documentText, createProgressIndicator(), oldFileNode.getText()); diffLog.doActualPsiChange(file); if (oldFileNode.getTextLength() != document.getTextLength()) { LOG.error("PSI is broken beyond repair in: " + file); } } finally { file.putUserData(BlockSupport.DO_NOT_REPARSE_INCREMENTALLY, null); } } }
private void assertAfterCommit(Document document, final PsiFile file, String oldPsiText, FileElement myTreeElementBeingReparsedSoItWontBeCollected) { if (myTreeElementBeingReparsedSoItWontBeCollected.getTextLength() != document.getTextLength()) { final String documentText = document.getText(); if (ApplicationManager.getApplication().isInternal()) { String fileText = file.getText(); LOG.error("commitDocument left PSI inconsistent; file len=" + myTreeElementBeingReparsedSoItWontBeCollected.getTextLength() + "; doc len=" + document.getTextLength() + "; doc.getText() == file.getText(): " + Comparing.equal(fileText, documentText) + ";\n file psi text=" + fileText + ";\n doc text=" + documentText + ";\n old psi file text=" + oldPsiText); } else { LOG.error("commitDocument left PSI inconsistent: " + file); } 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()); CodeStyleManager.getInstance(file.getProject()).performActionWithFormatterDisabled(new Runnable() { @Override public void run() { synchronized (PsiLock.LOCK) { 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); } } }
@Nonnull private static BooleanRunnable doCommit(@Nonnull final CommitTask task, @Nonnull final PsiFile file, @Nonnull final FileASTNode oldFileNode, @Nonnull ProperTextRange changedPsiRange, @Nonnull List<BooleanRunnable> outReparseInjectedProcessors) { Document document = task.getDocument(); final CharSequence newDocumentText = document.getImmutableCharSequence(); final Boolean data = document.getUserData(BlockSupport.DO_NOT_REPARSE_INCREMENTALLY); if (data != null) { document.putUserData(BlockSupport.DO_NOT_REPARSE_INCREMENTALLY, null); file.putUserData(BlockSupport.DO_NOT_REPARSE_INCREMENTALLY, data); } Trinity<DiffLog, ASTNode, ASTNode> result = BlockSupportImpl.reparse(file, oldFileNode, changedPsiRange, newDocumentText, task.indicator, task.myLastCommittedText); DiffLog diffLog = result.getFirst(); ASTNode oldRoot = result.getSecond(); ASTNode newRoot = result.getThird(); PsiDocumentManagerBase documentManager = (PsiDocumentManagerBase)PsiDocumentManager.getInstance(task.project); List<BooleanRunnable> injectedRunnables = documentManager.reparseChangedInjectedFragments(document, file, changedPsiRange, task.indicator, oldRoot, newRoot); outReparseInjectedProcessors.addAll(injectedRunnables); return () -> { FileViewProvider viewProvider = file.getViewProvider(); Document document1 = task.getDocument(); if (!task.isStillValid() || ((PsiDocumentManagerBase)PsiDocumentManager.getInstance(file.getProject())).getCachedViewProvider(document1) != viewProvider) { return false; // optimistic locking failed } if (!ApplicationManager.getApplication().isWriteAccessAllowed()) { VirtualFile vFile = viewProvider.getVirtualFile(); LOG.error("Write action expected" + "; document=" + document1 + "; file=" + file + " of " + file.getClass() + "; file.valid=" + file.isValid() + "; file.eventSystemEnabled=" + viewProvider.isEventSystemEnabled() + "; viewProvider=" + viewProvider + " of " + viewProvider.getClass() + "; language=" + file.getLanguage() + "; vFile=" + vFile + " of " + vFile.getClass() + "; free-threaded=" + AbstractFileViewProvider.isFreeThreaded(viewProvider)); } diffLog.doActualPsiChange(file); assertAfterCommit(document1, file, (FileElement)oldFileNode); return true; }; }