@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; }
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); } }); } }
public StubTree calcStubTree() { FileElement fileElement = calcTreeElement(); synchronized (myStubFromTreeLock) { SoftReference<StubTree> ref = fileElement.getUserData(STUB_TREE_IN_PARSED_TREE); StubTree tree = SoftReference.dereference(ref); if (tree == null) { ApplicationManager.getApplication().assertReadAccessAllowed(); IElementType contentElementType = getContentElementType(); if (!(contentElementType instanceof IStubFileElementType)) { VirtualFile vFile = getVirtualFile(); String message = "ContentElementType: " + contentElementType + "; file: " + this + "\n\t" + "Boolean.TRUE.equals(getUserData(BUILDING_STUB)) = " + Boolean.TRUE.equals(getUserData(BUILDING_STUB)) + "\n\t" + "getTreeElement() = " + getTreeElement() + "\n\t" + "vFile instanceof VirtualFileWithId = " + (vFile instanceof VirtualFileWithId) + "\n\t" + "StubUpdatingIndex.canHaveStub(vFile) = " + StubTreeLoader.getInstance().canHaveStub(vFile); rebuildStub(); throw new AssertionError(message); } StubElement currentStubTree = ((IStubFileElementType) contentElementType).getBuilder().buildStubTree(this); if (currentStubTree == null) { throw new AssertionError( "Stub tree wasn't built for " + contentElementType + "; file: " + this); } tree = new StubTree((PsiFileStub) currentStubTree); tree.setDebugInfo("created in calcStubTree"); try { TreeUtil.bindStubsToTree(this, tree); } catch (TreeUtil.StubBindingException e) { rebuildStub(); throw new RuntimeException("Stub and PSI element type mismatch in " + getName(), e); } fileElement.putUserData(STUB_TREE_IN_PARSED_TREE, new SoftReference<StubTree>(tree)); } return tree; } }
private void doClearCaches(String reason) { final FileElement tree = getTreeElement(); if (tree != null) { tree.clearCaches(); } synchronized (PsiLock.LOCK) { clearStub(reason); } if (tree != null) { tree.putUserData(STUB_TREE_IN_PARSED_TREE, null); } clearCaches(); }
@NotNull protected FileElement createFileElement(CharSequence docText) { final FileElement treeElement; final TreeElement contentLeaf = createContentLeafElement(docText); if (contentLeaf instanceof FileElement) { treeElement = (FileElement) contentLeaf; } else { final CompositeElement xxx = ASTFactory.composite(myElementType); assert xxx instanceof FileElement : "BUMM"; treeElement = (FileElement) xxx; treeElement.rawAddChildrenWithoutNotifications(contentLeaf); } return treeElement; }
protected PsiFileImpl cloneImpl(FileElement treeElementClone) { PsiFileImpl clone = (PsiFileImpl) super.clone(); clone.setTreeElementPointer( treeElementClone); // should not use setTreeElement here because cloned file still have // VirtualFile (SCR17963) treeElementClone.setPsi(clone); return clone; }
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(); } } }
@NotNull private FileElement loadTreeElement() { ApplicationManager.getApplication().assertReadAccessAllowed(); final FileViewProvider viewProvider = getViewProvider(); if (viewProvider.isPhysical() && myManager.isAssertOnFileLoading(viewProvider.getVirtualFile())) { LOG.error( "Access to tree elements not allowed in tests. path='" + viewProvider.getVirtualFile().getPresentableUrl() + "'"); } Document cachedDocument = FileDocumentManager.getInstance().getCachedDocument(getViewProvider().getVirtualFile()); FileElement treeElement = createFileElement(viewProvider.getContents()); treeElement.setPsi(this); List<Pair<StubBasedPsiElementBase, CompositeElement>> bindings = calcStubAstBindings(treeElement, cachedDocument); synchronized (PsiLock.LOCK) { FileElement existing = derefTreeElement(); if (existing != null) { return existing; } switchFromStubToAst(bindings); myStub = null; myTreeElementPointer = createTreeElementPointer(treeElement); if (LOG.isDebugEnabled() && viewProvider.isPhysical()) { LOG.debug("Loaded text for file " + viewProvider.getVirtualFile().getPresentableUrl()); } return treeElement; } }
private static void createActionsMap( final List<ASTNode> astNodes, final FileViewProvider provider, final TreeSet<PostprocessFormattingTask> rangesToProcess) { final Set<ASTNode> nodesToProcess = new HashSet<ASTNode>(astNodes); final Document document = provider.getDocument(); for (final ASTNode node : astNodes) { nodesToProcess.remove(node); final FileElement fileElement = TreeUtil.getFileElement((TreeElement) node); if (fileElement == null || ((PsiFile) fileElement.getPsi()).getViewProvider() != provider) continue; final boolean isGenerated = CodeEditUtil.isNodeGenerated(node); ((TreeElement) node) .acceptTree( new RecursiveTreeElementVisitor() { boolean inGeneratedContext = !isGenerated; protected boolean visitNode(TreeElement element) { if (nodesToProcess.contains(element)) return false; if (CodeEditUtil.isPostponedFormattingDisabled(element)) return false; final boolean currentNodeGenerated = CodeEditUtil.isNodeGenerated(element); CodeEditUtil.setNodeGenerated(element, false); if (currentNodeGenerated && !inGeneratedContext) { rangesToProcess.add( new ReformatTask(document.createRangeMarker(element.getTextRange()))); inGeneratedContext = true; } if (!currentNodeGenerated && inGeneratedContext) { if (element.getElementType() == TokenType.WHITE_SPACE) return false; final int oldIndent = CodeEditUtil.getOldIndentation(element); LOG.assertTrue( oldIndent >= 0, "for not generated items old indentation must be defined: element " + element); rangesToProcess.add( new ReindentTask( document.createRangeMarker(element.getTextRange()), oldIndent)); inGeneratedContext = false; } return true; } @Override public void visitComposite(CompositeElement composite) { boolean oldGeneratedContext = inGeneratedContext; super.visitComposite(composite); inGeneratedContext = oldGeneratedContext; } @Override public void visitLeaf(LeafElement leaf) { boolean oldGeneratedContext = inGeneratedContext; super.visitLeaf(leaf); inGeneratedContext = oldGeneratedContext; } }); CodeEditUtil.enablePostponedFormattingInTree(node); } }
/** * Parses the given <tt>parser</tt> in order to create a <tt>FileElement</tt> from it. * * @param parser the parser to parse * @see IQProvider#parseIQ(XmlPullParser) */ public IQ parseIQ(final XmlPullParser parser) throws Exception { boolean done = false; // si String id = parser.getAttributeValue("", "id"); String mimeType = parser.getAttributeValue("", "mime-type"); StreamInitiation initiation = new StreamInitiation(); // file String name = null; String size = null; String hash = null; String date = null; String desc = null; ThumbnailElement thumbnail = null; boolean isRanged = false; // feature DataForm form = null; DataFormProvider dataFormProvider = new DataFormProvider(); int eventType; String elementName; String namespace; while (!done) { eventType = parser.next(); elementName = parser.getName(); namespace = parser.getNamespace(); if (eventType == XmlPullParser.START_TAG) { if (elementName.equals("file")) { name = parser.getAttributeValue("", "name"); size = parser.getAttributeValue("", "size"); hash = parser.getAttributeValue("", "hash"); date = parser.getAttributeValue("", "date"); } else if (elementName.equals("desc")) { desc = parser.nextText(); } else if (elementName.equals("range")) { isRanged = true; } else if (elementName.equals("x") && namespace.equals("jabber:x:data")) { form = (DataForm) dataFormProvider.parseExtension(parser); } else if (elementName.equals("thumbnail")) { thumbnail = new ThumbnailElement(parser.getText()); } } else if (eventType == XmlPullParser.END_TAG) { if (elementName.equals("si")) { done = true; } // The name-attribute is required per XEP-0096, so ignore the // IQ if the name is not set to avoid exceptions. Particularly, // the SI response of Empathy contains an invalid, empty // file-tag. else if (elementName.equals("file") && name != null) { long fileSize = 0; if (size != null && size.trim().length() != 0) { try { fileSize = Long.parseLong(size); } catch (NumberFormatException e) { logger.warn( "Received an invalid file size," + " continuing with fileSize set to 0", e); } } FileElement file = new FileElement(name, fileSize); file.setHash(hash); if (date != null) { // try all known date formats boolean found = false; if (date.matches(".*?T\\d+:\\d+:\\d+(\\.\\d+)?(\\+|-)\\d+:\\d+")) { int timeZoneColon = date.lastIndexOf(":"); date = date.substring(0, timeZoneColon) + date.substring(timeZoneColon + 1, date.length()); } for (DateFormat fmt : DATE_FORMATS) { try { file.setDate(fmt.parse(date)); found = true; break; } catch (ParseException ex) { } } if (!found) { logger.warn("Unknown dateformat on incoming file transfer: " + date); } } if (thumbnail != null) file.setThumbnailElement(thumbnail); file.setDesc(desc); file.setRanged(isRanged); initiation.setFile(file); } } } initiation.setSesssionID(id); initiation.setMimeType(mimeType); initiation.setFeatureNegotiationForm(form); return initiation; }
private static void createActionsMap( @NotNull List<ASTNode> astNodes, @NotNull FileViewProvider provider, @NotNull final TreeSet<PostprocessFormattingTask> rangesToProcess) { final Set<ASTNode> nodesToProcess = new HashSet<ASTNode>(astNodes); final Document document = provider.getDocument(); if (document == null) { return; } for (final ASTNode node : astNodes) { nodesToProcess.remove(node); final FileElement fileElement = TreeUtil.getFileElement((TreeElement) node); if (fileElement == null || ((PsiFile) fileElement.getPsi()).getViewProvider() != provider) continue; final boolean isGenerated = CodeEditUtil.isNodeGenerated(node); ((TreeElement) node) .acceptTree( new RecursiveTreeElementVisitor() { boolean inGeneratedContext = !isGenerated; @Override protected boolean visitNode(TreeElement element) { if (nodesToProcess.contains(element)) return false; final boolean currentNodeGenerated = CodeEditUtil.isNodeGenerated(element); CodeEditUtil.setNodeGenerated(element, false); if (currentNodeGenerated && !inGeneratedContext) { rangesToProcess.add( new ReformatTask(document.createRangeMarker(element.getTextRange()))); inGeneratedContext = true; } if (!currentNodeGenerated && inGeneratedContext) { if (element.getElementType() == TokenType.WHITE_SPACE) return false; final int oldIndent = CodeEditUtil.getOldIndentation(element); CodeEditUtil.setOldIndentation(element, -1); LOG.assertTrue( oldIndent >= 0, "for not generated items old indentation must be defined: element " + element); for (TextRange indentRange : getEnabledRanges(element.getPsi())) { rangesToProcess.add( new ReindentTask(document.createRangeMarker(indentRange), oldIndent)); } inGeneratedContext = false; } return true; } private Iterable<TextRange> getEnabledRanges(@NotNull PsiElement element) { List<TextRange> disabledRanges = new ArrayList<TextRange>(); for (DisabledIndentRangesProvider rangesProvider : DisabledIndentRangesProvider.EP_NAME.getExtensions()) { Collection<TextRange> providedDisabledRanges = rangesProvider.getDisabledIndentRanges(element); if (providedDisabledRanges != null) { disabledRanges.addAll(providedDisabledRanges); } } return TextRangeUtil.excludeRanges(element.getTextRange(), disabledRanges); } @Override public void visitComposite(CompositeElement composite) { boolean oldGeneratedContext = inGeneratedContext; super.visitComposite(composite); inGeneratedContext = oldGeneratedContext; } @Override public void visitLeaf(LeafElement leaf) { boolean oldGeneratedContext = inGeneratedContext; super.visitLeaf(leaf); inGeneratedContext = oldGeneratedContext; } }); } }