public PsiClassStubImpl(final JavaClassElementType type, final StubElement parent, final StringRef qualifiedName, final StringRef name, final StringRef baseRefText, final byte flags) { super(parent, type); myQualifiedName = qualifiedName; myName = name; myBaseRefText = baseRefText; myFlags = flags; if (StubBasedPsiElementBase.ourTraceStubAstBinding) { String creationTrace = "Stub creation thread: " + Thread.currentThread() + "\n" + DebugUtil.currentStackTrace(); putUserData(StubBasedPsiElementBase.CREATION_TRACE, creationTrace); } }
public static void addImportForItem(InsertionContext context, PsiClass aClass) { if (aClass.getQualifiedName() == null) return; PsiFile file = context.getFile(); int startOffset = context.getStartOffset(); int tail = context.getTailOffset(); int newTail = JavaCompletionUtil.insertClassReference(aClass, file, startOffset, tail); if (newTail > context.getDocument().getTextLength() || newTail < 0) { LOG.error(LogMessageEx.createEvent("Invalid offset after insertion ", "offset=" + newTail + "\n" + "start=" + startOffset + "\n" + "tail=" + tail + "\n" + "file.length=" + file.getTextLength() + "\n" + "document=" + context.getDocument() + "\n" + DebugUtil.currentStackTrace(), AttachmentFactory.createAttachment(context.getDocument()))); return; } context.setTailOffset(newTail); JavaCompletionUtil.shortenReference(file, context.getStartOffset()); PostprocessReformattingAspect.getInstance(context.getProject()).doPostponedFormatting(); }
public void testSOEProof() { final StringBuilder sb = new StringBuilder(); final SecureRandom random = new SecureRandom(); sb.append("class SOE_test {\n BigInteger BIG = new BigInteger(\n"); int i; for (i = 0; i < 100000; i++) { sb.append(" \"").append(Math.abs(random.nextInt())).append("\" +\n"); } sb.append(" \"\");\n}"); final PsiJavaFile file = (PsiJavaFile)createLightFile("SOE_test.java", sb.toString()); long t = System.currentTimeMillis(); final StubElement tree = NEW_BUILDER.buildStubTree(file); t = System.currentTimeMillis() - t; assertEquals("PsiJavaFileStub []\n" + " IMPORT_LIST:PsiImportListStub\n" + " CLASS:PsiClassStub[name=SOE_test fqn=SOE_test]\n" + " MODIFIER_LIST:PsiModifierListStub[mask=4096]\n" + " TYPE_PARAMETER_LIST:PsiTypeParameterListStub\n" + " EXTENDS_LIST:PsiRefListStub[EXTENDS_LIST:]\n" + " IMPLEMENTS_LIST:PsiRefListStub[IMPLEMENTS_LIST:]\n" + " FIELD:PsiFieldStub[BIG:BigInteger=;INITIALIZER_NOT_STORED;]\n" + " MODIFIER_LIST:PsiModifierListStub[mask=4096]\n", DebugUtil.stubTreeToString(tree)); System.out.println("SOE depth=" + i + ", time=" + t + "ms"); }
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()); }
public void testSOEProof() { StringBuilder sb = new StringBuilder(); SecureRandom random = new SecureRandom(); sb.append("class SOE_test {\n BigInteger BIG = new BigInteger(\n"); int i; for (i = 0; i < 100000; i++) { sb.append(" \"").append(Math.abs(random.nextInt())).append("\" +\n"); } sb.append(" \"\");\n}"); PsiJavaFile file = (PsiJavaFile)createLightFile("SOE_test.java", sb.toString()); long t = System.currentTimeMillis(); StubElement tree = myBuilder.buildStubTree(file); t = System.currentTimeMillis() - t; assertEquals("PsiJavaFileStub []\n" + " IMPORT_LIST:PsiImportListStub\n" + " CLASS:PsiClassStub[name=SOE_test fqn=SOE_test]\n" + " MODIFIER_LIST:PsiModifierListStub[mask=4096]\n" + " TYPE_PARAMETER_LIST:PsiTypeParameterListStub\n" + " EXTENDS_LIST:PsiRefListStub[EXTENDS_LIST:]\n" + " IMPLEMENTS_LIST:PsiRefListStub[IMPLEMENTS_LIST:]\n" + " FIELD:PsiFieldStub[BIG:BigInteger=;INITIALIZER_NOT_STORED;]\n" + " MODIFIER_LIST:PsiModifierListStub[mask=4096]\n", DebugUtil.stubTreeToString(tree)); System.out.println("SOE depth=" + i + ", time=" + t + "ms"); }
private void doTest(String source, String expected) { PsiJavaFile file = (PsiJavaFile)createLightFile("test.java", source); FileASTNode fileNode = file.getNode(); assertNotNull(fileNode); assertFalse(fileNode.isParsed()); StubElement lightTree = myBuilder.buildStubTree(file); assertFalse(fileNode.isParsed()); file.getNode().getChildren(null); // force switch to AST StubElement astBasedTree = myBuilder.buildStubTree(file); assertTrue(fileNode.isParsed()); assertEquals("light tree differs", expected, DebugUtil.stubTreeToString(lightTree)); assertEquals("AST-based tree differs", expected, DebugUtil.stubTreeToString(astBasedTree)); }
@Override @NotNull public PsiElement getElementAtCaret() { assertInitialized(); Editor editor = getCompletionEditor(); int findTargetFlags = TargetElementUtil.REFERENCED_ELEMENT_ACCEPTED | TargetElementUtil.ELEMENT_NAME_ACCEPTED; PsiElement element = TargetElementUtil.findTargetElement(editor, findTargetFlags); // if no references found in injected fragment, try outer document if (element == null && editor instanceof EditorWindow) { element = TargetElementUtil.findTargetElement(((EditorWindow)editor).getDelegate(), findTargetFlags); } if (element == null) { Assert.fail("element not found in file " + myFile.getName() + " at caret position offset " + myEditor.getCaretModel().getOffset() + "," + " psi structure:\n" + DebugUtil.psiToString(getFile(), true, true)); } return element; }
public void actionPerformed(final AnActionEvent e) { if (myLagging) { myLagging = false; myAlarm.cancelAllRequests(); } else { myLagging = true; for (int i = 0; i < 100; i++) { new Runnable() { @Override public void run() { DebugUtil.sleep(5); ProgressManager.getInstance().runProcessWithProgressAsynchronously(new Task.Backgroundable(null, "lagging") { @Override public void run(@NotNull ProgressIndicator indicator) { DebugUtil.sleep(1); } }, new EmptyProgressIndicator()); if (myLagging) { myAlarm.addRequest(this, 1); } } }.run(); } } }
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); }
public void rawAddChildrenWithoutNotifications(TreeElement first) { final TreeElement last = getLastChildNode(); if (last == null){ first.rawRemoveUpToWithoutNotifications(null, false); setFirstChildNode(first); while(true){ final TreeElement treeNext = first.getTreeNext(); first.setTreeParent(this); if(treeNext == null) break; first = treeNext; } setLastChildNode(first); first.setTreeParent(this); } else { last.rawInsertAfterMeWithoutNotifications(first); } DebugUtil.checkTreeStructure(this); }
public void rawRemove() { final TreeElement next = getTreeNext(); final CompositeElement parent = getTreeParent(); final TreeElement prev = getTreePrev(); if(prev != null){ prev.setTreeNext(next); } else if(parent != null) { parent.setFirstChildNode(next); } if(next != null){ next.setTreePrev(prev); } else if(parent != null) { parent.setLastChildNode(prev); } DebugUtil.checkTreeStructure(parent); DebugUtil.checkTreeStructure(prev); DebugUtil.checkTreeStructure(next); invalidate(); }
@Override void doActualPsiChange(@NotNull PsiFile file, @NotNull ASTDiffBuilder astDiffBuilder) { ASTNode child = myOldNode; ASTNode parent = myOldParent; PsiElement psiParent = parent.getPsi(); PsiElement psiChild = file.isPhysical() ? child.getPsi() : null; if (psiParent != null && psiChild != null) { PsiTreeChangeEventImpl event = new PsiTreeChangeEventImpl(file.getManager()); event.setParent(psiParent); event.setChild(psiChild); event.setFile(file); ((PsiManagerEx)file.getManager()).beforeChildRemoval(event); } astDiffBuilder.nodeDeleted(parent, child); ((TreeElement)child).rawRemove(); ((CompositeElement)parent).subtreeChanged(); DebugUtil.checkTreeStructure(parent); }
private void watchTail(int offset) { stopWatching(); tailWatcher = (RangeMarkerEx)getDocument().createRangeMarker(offset, offset); if (!tailWatcher.isValid()) { throw new AssertionError(getDocument() + "; offset=" + offset); } tailWatcher.setGreedyToRight(true); spy = new RangeMarkerSpy(tailWatcher) { @Override protected void invalidated(DocumentEvent e) { if (ApplicationManager.getApplication().isUnitTestMode()) { LOG.error("Tail offset invalidated, say thanks to the "+ e); } if (invalidateTrace == null) { invalidateTrace = DebugUtil.currentStackTrace(); killer = e; } } }; getDocument().addDocumentListener(spy); }
@NotNull @Override protected Action[] createActions() { AbstractAction copyPsi = new AbstractAction("Cop&y PSI") { @Override public void actionPerformed(@NotNull ActionEvent e) { PsiElement element = parseText(myEditor.getDocument().getText()); List<PsiElement> allToParse = new ArrayList<PsiElement>(); if (element instanceof PsiFile) { allToParse.addAll(((PsiFile)element).getViewProvider().getAllFiles()); } else if (element != null) { allToParse.add(element); } String data = ""; for (PsiElement psiElement : allToParse) { data += DebugUtil.psiToString(psiElement, !myShowWhiteSpacesBox.isSelected(), true); } CopyPasteManager.getInstance().setContents(new StringSelection(data)); } }; return ArrayUtil.mergeArrays(new Action[]{copyPsi}, super.createActions()); }
@Override protected Object stubTreeAndIndexDoNotMatch(@NotNull ObjectStubTree stubTree, PsiFileWithStubSupport psiFile) { final VirtualFile virtualFile = psiFile.getVirtualFile(); StubTree stubTreeFromIndex = (StubTree)StubTreeLoader.getInstance().readFromVFile(psiFile.getProject(), virtualFile); String details = "Please report the problem to JetBrains with the file attached"; details += StubTreeLoader.getInstance().getStubAstMismatchDiagnostics(virtualFile, psiFile, stubTree, null); details += "\n" + DebugUtil.currentStackTrace(); String fileText = psiFile instanceof PsiCompiledElement ? "compiled" : psiFile.getText(); return LogMessageEx.createEvent("PSI and index do not match", details, new Attachment(virtualFile.getPath() + "_file.txt", fileText), new Attachment("stubTree.txt", ((PsiFileStubImpl)stubTree.getRoot()).printTree()), new Attachment("stubTreeFromIndex.txt", stubTreeFromIndex == null ? "null" : ((PsiFileStubImpl)stubTreeFromIndex.getRoot()).printTree())); }
private static boolean cacheEverything(@NotNull Place place, @NotNull DocumentWindowImpl documentWindow, @NotNull InjectedFileViewProvider viewProvider, @NotNull PsiFile psiFile, @NotNull SmartPsiElementPointer<PsiLanguageInjectionHost> pointer) { FileDocumentManagerImpl.registerDocument(documentWindow, viewProvider.getVirtualFile()); DebugUtil.startPsiModification("MultiHostRegistrar cacheEverything"); try { viewProvider.forceCachedPsi(psiFile); } finally { DebugUtil.finishPsiModification(); } psiFile.putUserData(FileContextUtil.INJECTED_IN_ELEMENT, pointer); PsiDocumentManagerBase.cachePsi(documentWindow, psiFile); keepTreeFromChameleoningBack(psiFile); return viewProvider.setShreds(place, psiFile.getProject()); }
public void testScripts() throws Exception { final String f = file.getAbsolutePath(); final byte[] bytes = Files.readAllBytes(Paths.get(f)); final String content = new String(bytes); final long start = System.currentTimeMillis(); final ASTNode tree = parse(content); final long time = System.currentTimeMillis() - start; final String msg = String.format( "%-30s %8sms %10.2fKB", testFileName, time, bytes.length/1024.0 ); final String s = DebugUtil.nodeTreeToString(tree, true); if (hasParseError(s)) { throw new RuntimeException(s); } else { System.out.println(msg); } }
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); }
static void assertCompletionPositionPsiConsistent(CompletionContext newContext, int offset, PsiFile fileCopy, PsiFile originalFile, PsiElement insertedElement) { if (insertedElement == null) { throw new LogEventException("No element at insertion offset", "offset=" + newContext.getStartOffset() + "\n" + DebugUtil.currentStackTrace(), createFileTextAttachment(fileCopy, originalFile), createAstAttachment(fileCopy, originalFile)); } if (fileCopy.findElementAt(offset) != insertedElement) { throw new AssertionError("wrong offset"); } final TextRange range = insertedElement.getTextRange(); if (!range.substring(fileCopy.getText()).equals(insertedElement.getText())) { throw new LogEventException("Inconsistent completion tree", "range=" + range + "\n" + DebugUtil.currentStackTrace(), createFileTextAttachment(fileCopy, originalFile), createAstAttachment(fileCopy, originalFile), new Attachment("Element at caret.txt", insertedElement.getText())); } }
@NotNull @Override protected Action[] createActions() { AbstractAction copyPsi = new AbstractAction("Cop&y PSI") { @Override public void actionPerformed(ActionEvent e) { PsiElement element = parseText(myEditor.getDocument().getText()); List<PsiElement> allToParse = new ArrayList<PsiElement>(); if (element instanceof PsiFile) { allToParse.addAll(((PsiFile)element).getViewProvider().getAllFiles()); } else if (element != null) { allToParse.add(element); } String data = ""; for (PsiElement psiElement : allToParse) { data += DebugUtil.psiToString(psiElement, !myShowWhiteSpacesBox.isSelected(), true); } CopyPasteManager.getInstance().setContents(new StringSelection(data)); } }; return ArrayUtil.mergeArrays(new Action[]{copyPsi}, super.createActions()); }
protected ProjectImpl(@Nonnull ProjectManager manager, @Nonnull String dirPath, boolean isOptimiseTestLoadSpeed, String projectName) { super(ApplicationManager.getApplication(), "Project " + (projectName == null ? dirPath : projectName)); putUserData(CREATION_TIME, System.nanoTime()); if (ApplicationManager.getApplication().isUnitTestMode()) { putUserData(CREATION_TRACE, DebugUtil.currentStackTrace()); } getPicoContainer().registerComponentInstance(Project.class, this); if (!isDefault()) { getStateStore().setProjectFilePath(dirPath); } myOptimiseTestLoadSpeed = isOptimiseTestLoadSpeed; myManager = manager; myName = isDefault() ? TEMPLATE_PROJECT_NAME : projectName == null ? getStateStore().getProjectName() : projectName; }
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)); }
public void rawAddChildrenWithoutNotifications(@Nonnull TreeElement first) { if (DebugUtil.DO_EXPENSIVE_CHECKS && !(this instanceof LazyParseableElement)) { PsiFileImpl file = getCachedFile(this); if (file != null && !file.useStrongRefs()) { throw new AssertionError("Attempt to modify PSI in a file with weakly-referenced AST. Possible cause: missing PomTransaction."); } } final TreeElement last = getLastChildNode(); if (last == null){ TreeElement chainLast = rawSetParents(first, this); setFirstChildNode(first); setLastChildNode(chainLast); } else { last.rawInsertAfterMeWithoutNotifications(first); } DebugUtil.checkTreeStructure(this); }
@Override public void setViewProvider(@Nonnull final VirtualFile virtualFile, @Nullable final FileViewProvider fileViewProvider) { FileViewProvider prev = findCachedViewProvider(virtualFile); if (prev == fileViewProvider) return; if (prev != null) { DebugUtil.performPsiModification(null, () -> { markInvalidated(prev); DebugUtil.onInvalidated(prev); }); } if (fileViewProvider == null) { getVFileToViewProviderMap().remove(virtualFile); } else if (virtualFile instanceof LightVirtualFile) { virtualFile.putUserData(myPsiHardRefKey, fileViewProvider); } else { getVFileToViewProviderMap().put(virtualFile, fileViewProvider); } }
void processFileTypesChanged() { if (myProcessingFileTypesChange) return; myProcessingFileTypesChange = true; DebugUtil.performPsiModification(null, () -> { try { ApplicationManager.getApplication().runWriteAction(() -> { PsiTreeChangeEventImpl event = new PsiTreeChangeEventImpl(myManager); event.setPropertyName(PsiTreeChangeEvent.PROP_FILE_TYPES); myManager.beforePropertyChange(event); invalidateAllPsi(); myManager.propertyChanged(event); }); } finally { myProcessingFileTypesChange = false; } }); }
void removeFilesAndDirsRecursively(@Nonnull VirtualFile vFile) { DebugUtil.performPsiModification("removeFilesAndDirsRecursively", () -> { VfsUtilCore.visitChildrenRecursively(vFile, new VirtualFileVisitor() { @Override public boolean visitFile(@Nonnull VirtualFile file) { if (file.isDirectory()) { getVFileToPsiDirMap().remove(file); } else { FileViewProvider viewProvider = getVFileToViewProviderMap().remove(file); if (viewProvider != null) { markInvalidated(viewProvider); } } return true; } }); }); }
@Nonnull @Override protected Action[] createActions() { AbstractAction copyPsi = new AbstractAction("Cop&y PSI") { @Override public void actionPerformed(ActionEvent e) { PsiElement element = parseText(myEditor.getDocument().getText()); List<PsiElement> allToParse = new ArrayList<PsiElement>(); if (element instanceof PsiFile) { allToParse.addAll(((PsiFile)element).getViewProvider().getAllFiles()); } else if (element != null) { allToParse.add(element); } String data = ""; for (PsiElement psiElement : allToParse) { data += DebugUtil.psiToString(psiElement, !myShowWhiteSpacesBox.isSelected(), true); } CopyPasteManager.getInstance().setContents(new StringSelection(data)); } }; return ArrayUtil.mergeArrays(new Action[]{copyPsi}, super.createActions()); }
public PsiClassStubImpl(final JavaClassElementType type, final StubElement parent, @Nullable final String qualifiedName, @Nullable final String name, @Nullable final String baseRefText, final byte flags) { super(parent, type); myQualifiedName = qualifiedName; myName = name; myBaseRefText = baseRefText; myFlags = flags; if(StubBasedPsiElementBase.ourTraceStubAstBinding) { String creationTrace = "Stub creation thread: " + Thread.currentThread() + "\n" + DebugUtil.currentStackTrace(); putUserData(StubBasedPsiElementBase.CREATION_TRACE, creationTrace); } }
private void diagnoseUnknownParent() { CompositeElement parent = getTreeParent(); IElementType i = parent.getElementType(); String message = "Unknown parent for java code reference: '" + parent + "'; Type: " + i + ";\n"; while(parent != null && parent.getPsi() instanceof PsiExpression) { parent = parent.getTreeParent(); message += " Parent: '" + parent + "'; \n"; } if(parent != null) { message += DebugUtil.treeToString(parent, false); } LOG.error(message); }
private void addTrace(@Nullable PsiClassStub stub) { if(ourTraceStubAstBinding) { String creationTrace = "Creation thread: " + Thread.currentThread() + "\n" + DebugUtil.currentStackTrace(); if(stub != null) { creationTrace += "\nfrom stub " + stub + "@" + System.identityHashCode(stub) + "\n"; if(stub instanceof UserDataHolder) { String stubTrace = ((UserDataHolder) stub).getUserData(CREATION_TRACE); if(stubTrace != null) { creationTrace += stubTrace; } } } putUserData(CREATION_TRACE, creationTrace); } }
public static void addImportForItem(InsertionContext context, PsiClass aClass) { if(aClass.getQualifiedName() == null) { return; } PsiFile file = context.getFile(); int startOffset = context.getStartOffset(); int tail = context.getTailOffset(); int newTail = JavaCompletionUtil.insertClassReference(aClass, file, startOffset, tail); if(newTail > context.getDocument().getTextLength() || newTail < 0) { LOG.error(LogMessageEx.createEvent("Invalid offset after insertion ", "offset=" + newTail + "\n" + "start=" + startOffset + "\n" + "tail=" + tail + "\n" + "file.length=" + file .getTextLength() + "\n" + "document=" + context.getDocument() + "\n" + DebugUtil.currentStackTrace(), AttachmentFactory.createAttachment(context.getDocument()))); return; } context.setTailOffset(newTail); JavaCompletionUtil.shortenReference(file, context.getStartOffset()); PostprocessReformattingAspect.getInstance(context.getProject()).doPostponedFormatting(); }