Example #1
0
  @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);
           }
         });
   }
 }
Example #3
0
  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;
    }
  }
Example #4
0
  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();
  }
Example #5
0
  @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;
  }
Example #6
0
 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;
 }
Example #7
0
 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();
     }
   }
 }
Example #8
0
  @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);
    }
  }
Example #10
0
  /**
   * 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;
                }
              });
    }
  }