All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.intellij.psi.impl.source.xml.XmlEntityDeclImpl Maven / Gradle / Ivy

Go to download

A packaging of the IntelliJ Community Edition xml-psi-impl library. This is release number 1 of trunk branch 142.

The newest version!
/*
 * Copyright 2000-2014 JetBrains s.r.o.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.intellij.psi.impl.source.xml;

import com.intellij.lang.ASTNode;
import com.intellij.openapi.util.TextRange;
import com.intellij.pom.Navigatable;
import com.intellij.psi.ElementManipulators;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiNamedElement;
import com.intellij.psi.impl.source.SourceTreeToPsiMap;
import com.intellij.psi.impl.source.parsing.xml.DtdParsing;
import com.intellij.psi.tree.xml.IXmlLeafElementType;
import com.intellij.psi.xml.*;
import com.intellij.util.IncorrectOperationException;
import com.intellij.xml.util.XmlUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

/**
 * @author mike
 */
public class XmlEntityDeclImpl extends XmlElementImpl implements XmlEntityDecl, XmlElementType {
  public XmlEntityDeclImpl() {
    super(XML_ENTITY_DECL);
  }

  @Override
  public PsiElement getNameElement() {
    for (ASTNode e = getFirstChildNode(); e != null; e = e.getTreeNext()) {
      if (e instanceof XmlTokenImpl) {
        XmlTokenImpl xmlToken = (XmlTokenImpl)e;

        if (xmlToken.getTokenType() == XmlTokenType.XML_NAME) return xmlToken;
      }
    }

    return null;
  }

  @Override
  public XmlAttributeValue getValueElement() {
    if (isInternalReference()) {
      for (ASTNode e = getFirstChildNode(); e != null; e = e.getTreeNext()) {
        if (e.getElementType() == XmlElementType.XML_ATTRIBUTE_VALUE) {
          return (XmlAttributeValue)SourceTreeToPsiMap.treeElementToPsi(e);
        }
      }
    }
    else {
      for (ASTNode e = getLastChildNode(); e != null; e = e.getTreePrev()) {
        if (e.getElementType() == XmlElementType.XML_ATTRIBUTE_VALUE) {
          return (XmlAttributeValue)SourceTreeToPsiMap.treeElementToPsi(e);
        }
      }
    }

    return null;
  }

  @Override
  public String getName() {
    PsiElement nameElement = getNameElement();
    return nameElement != null ? nameElement.getText() : "";
  }

  @Override
  public PsiElement setName(@NotNull String name) throws IncorrectOperationException {
    final PsiElement nameElement = getNameElement();

    if (nameElement != null) {
      return ElementManipulators.getManipulator(nameElement).handleContentChange(
        nameElement,
        new TextRange(0,nameElement.getTextLength()),
        name
      );
    }
    return null;
  }

  @Override
  public PsiElement parse(PsiFile baseFile, EntityContextType contextType, final XmlEntityRef originalElement) {
    PsiElement dep = XmlElement.DEPENDING_ELEMENT.get(getParent());
    PsiElement dependsOnElement = getValueElement(dep instanceof PsiFile ? (PsiFile)dep : baseFile);
    String value = null;
    if (dependsOnElement instanceof XmlAttributeValue) {
      XmlAttributeValue attributeValue = (XmlAttributeValue)dependsOnElement;
      value = attributeValue.getValue();
    }
    else if (dependsOnElement instanceof PsiFile) {
      PsiFile file = (PsiFile)dependsOnElement;
      value = file.getText();
    }

    if (value == null) return null;

    DtdParsing dtdParsing = new DtdParsing(value, XML_ELEMENT_DECL, contextType, baseFile);
    PsiElement generated = dtdParsing.parse().getPsi().getFirstChild();
    if (contextType == EntityContextType.ELEMENT_CONTENT_SPEC && generated instanceof XmlElementContentSpec) {
      generated = generated.getFirstChild();
    }
    setDependsOnElement(generated, dependsOnElement);
    return setOriginalElement(generated, originalElement);
  }

  private PsiElement setDependsOnElement(PsiElement generated, PsiElement dependsOnElement) {
    PsiElement e = generated;
    while (e != null) {
      e.putUserData(XmlElement.DEPENDING_ELEMENT, dependsOnElement);
      e = e.getNextSibling();
    }
    return generated;
  }

  private PsiElement setOriginalElement(PsiElement element, PsiElement valueElement) {
    PsiElement e = element;
    while (e != null) {
      e.putUserData(XmlElement.INCLUDING_ELEMENT, (XmlElement)valueElement);
      e = e.getNextSibling();
    }
    return element;
  }

  @Nullable
  private PsiElement getValueElement(PsiFile baseFile) {
    final XmlAttributeValue attributeValue = getValueElement();
    if (isInternalReference()) return attributeValue;

    if (attributeValue != null) {
      final String value = attributeValue.getValue();
      if (value != null) {
        XmlFile xmlFile = XmlUtil.findNamespaceByLocation(baseFile, value);
        if (xmlFile != null) {
          return xmlFile;
        }

        final int i = XmlUtil.getPrefixLength(value);
        if (i > 0) {
          return XmlUtil.findNamespaceByLocation(baseFile, value.substring(i));
        }
      }
    }

    return null;
  }

  @Override
  public boolean isInternalReference() {
    for (ASTNode e = getFirstChildNode(); e != null; e = e.getTreeNext()) {
      if (e.getElementType() instanceof IXmlLeafElementType) {
        XmlToken token = (XmlToken)SourceTreeToPsiMap.treeElementToPsi(e);
        if (token.getTokenType() == XmlTokenType.XML_DOCTYPE_PUBLIC ||
            token.getTokenType() == XmlTokenType.XML_DOCTYPE_SYSTEM) {
          return false;
        }
      }
    }

    return true;
  }

  @Override
  @NotNull
  public PsiElement getNavigationElement() {
    return getNameElement();
  }

  @Override
  public int getTextOffset() {
    final PsiElement name = getNameElement();
    return name != null ? name.getTextOffset() : super.getTextOffset();
  }

  @Override
  public boolean canNavigate() {
    if (isPhysical()) return super.canNavigate();
    final PsiNamedElement psiNamedElement = XmlUtil.findRealNamedElement(this);
    return psiNamedElement != null;
  }

  @Override
  public void navigate(final boolean requestFocus) {
    if (!isPhysical()) {
      ((Navigatable)XmlUtil.findRealNamedElement(this)).navigate(requestFocus);
      return;
    }
    super.navigate(requestFocus);
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy