implementing references for ant dom implementation, some basic stuff

This commit is contained in:
Eugene Zhuravlev
2010-04-14 13:55:09 +04:00
parent 60da2faeaa
commit ffe522cf40
5 changed files with 223 additions and 2 deletions
@@ -0,0 +1,79 @@
/*
* Copyright 2000-2010 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.lang.ant.dom;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.PsiElement;
import com.intellij.psi.xml.XmlAttribute;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.StringBuilderSpinAllocator;
import org.jetbrains.annotations.NotNull;
/**
* @author Eugene Zhuravlev
* Date: Apr 13, 2010
*/
class AntDomDependentTargetReference extends AntDomReference {
public AntDomDependentTargetReference(AntDomTarget target, String targetName, int start) {
super(target, targetName, TextRange.from(start, start + targetName.length()));
}
public PsiElement handleElementRename(String newElementName) throws IncorrectOperationException {
final AntDomTarget hostTarget = getAntElement();
final XmlAttribute dependsAttribute = hostTarget.getDependsList().getXmlAttribute();
if (dependsAttribute != null) {
final TextRange refRange = getRangeInElement();
final int start = refRange.getStartOffset();
final String value = hostTarget.getDependsList().getValue();
final StringBuilder builder = StringBuilderSpinAllocator.alloc();
try {
if (start > 0) {
builder.append(value.substring(0, start));
}
builder.append(newElementName);
if (value.length() > start + refRange.getLength()) {
builder.append(value.substring(start + refRange.getLength()));
}
dependsAttribute.setValue(builder.toString());
}
finally {
StringBuilderSpinAllocator.dispose(builder);
}
}
return getElement();
}
public PsiElement bindToElement(@NotNull PsiElement element) throws IncorrectOperationException {
return null; // todo
}
public AntDomTarget getAntElement() {
return (AntDomTarget)super.getAntElement();
}
public PsiElement resolveInner() {
// todo: handle imported targets
final AntDomProject antProject = getAntElement().getAntProject();
if (antProject == null) {
return null;
}
final AntDomTarget resolved = antProject.getTarget(getCanonicalText());
if (resolved == null) {
return null;
}
return resolved.getXmlElement();
}
}
@@ -25,6 +25,7 @@ import com.intellij.util.xml.Attribute;
import com.intellij.util.xml.GenericAttributeValue;
import com.intellij.util.xml.SubTagList;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.List;
@@ -46,7 +47,17 @@ public abstract class AntDomProject extends AntDomElement {
public abstract GenericAttributeValue<String> getBasedir();
@SubTagList("target")
public abstract List<AntTarget> getTargets();
public abstract List<AntDomTarget> getTargets();
@Nullable
public final AntDomTarget getTarget(String name) {
for (AntDomTarget target : getTargets()) {
if (name.equals(target.getName().getValue())) {
return target;
}
}
return null;
}
@NotNull
public final ClassLoader getClassLoader() {
@@ -0,0 +1,70 @@
/*
* Copyright 2000-2010 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.lang.ant.dom;
import com.intellij.codeInsight.CodeInsightBundle;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.PsiElement;
import com.intellij.psi.impl.source.resolve.reference.impl.CachingReference;
import com.intellij.util.ArrayUtil;
import org.jetbrains.annotations.NotNull;
/**
* @author Eugene Zhuravlev
* Date: Apr 13, 2010
*/
public abstract class AntDomReference extends CachingReference{
private final AntDomElement myAntElement;
private final String myText;
private final TextRange myTextRange;
protected AntDomReference(final AntDomElement element, final String text, final TextRange textRange) {
myAntElement = element;
myText = text;
myTextRange = textRange;
}
public AntDomElement getAntElement() {
return myAntElement;
}
public PsiElement getElement() {
return myAntElement.getXmlElement();
}
public TextRange getRangeInElement() {
return myTextRange;
}
public String getCanonicalText() {
return myText;
}
@NotNull
public Object[] getVariants() {
return ArrayUtil.EMPTY_OBJECT_ARRAY;
}
@Override
public PsiElement resolveInner() {
throw new UnsupportedOperationException();
}
public String getUnresolvedMessagePattern() {
return CodeInsightBundle.message("error.cannot.resolve.default.message", "");
}
}
@@ -23,7 +23,7 @@ import com.intellij.util.xml.GenericAttributeValue;
* Date: Apr 6, 2010
*/
@SuppressWarnings({"AbstractClassNeverImplemented"})
public abstract class AntTarget extends AntDomElement {
public abstract class AntDomTarget extends AntDomElement {
@Attribute("name")
public abstract GenericAttributeValue<String> getName();
@@ -32,4 +32,11 @@ public abstract class AntTarget extends AntDomElement {
@Attribute("unless")
public abstract GenericAttributeValue<String> getUnlessPropertyName();
@Attribute("depends")
public abstract GenericAttributeValue<String> getDependsList();
public AntDomProject getAntProject() {
return getParentOfType(AntDomProject.class, true);
}
}
@@ -15,14 +15,20 @@
*/
package com.intellij.lang.ant.dom;
import com.intellij.lang.ant.misc.PsiReferenceListSpinAllocator;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiReference;
import com.intellij.psi.xml.XmlAttribute;
import com.intellij.util.StringBuilderSpinAllocator;
import com.intellij.util.xml.ConvertContext;
import com.intellij.util.xml.DomElement;
import com.intellij.util.xml.DomReferenceInjector;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Collections;
import java.util.List;
/**
* @author Eugene Zhuravlev
* Date: Apr 9, 2010
@@ -37,4 +43,52 @@ class AntReferenceInjector implements DomReferenceInjector {
public PsiReference[] inject(@Nullable String unresolvedText, @NotNull PsiElement element, @NotNull ConvertContext context) {
return PsiReference.EMPTY_ARRAY;
}
private List<PsiReference> getDependentTargetReferences(AntDomTarget target) {
final String xmlAttributeValue = target.getDependsList().getValue();
if (xmlAttributeValue == null) {
return Collections.emptyList();
}
final XmlAttribute attr = target.getDependsList().getXmlAttribute();
if (attr == null) {
return Collections.emptyList();
}
final int offsetInPosition = attr.getValueTextRange().getStartOffset();
final List<PsiReference> result = PsiReferenceListSpinAllocator.alloc();
try {
final StringBuilder builder = StringBuilderSpinAllocator.alloc();
try {
int i = 0;
int rightBound;
final int valueLen = xmlAttributeValue.length();
do {
rightBound = (i < valueLen) ? xmlAttributeValue.indexOf(',', i) : valueLen;
if (rightBound < 0) rightBound = valueLen;
builder.setLength(0);
int j = i;
for (; j < rightBound; ++j) {
builder.append(xmlAttributeValue.charAt(j));
}
j = 0;
final int len = builder.length();
for (; j < len; ++j) {
if (!Character.isWhitespace(builder.charAt(j))) break;
}
final String targetName = (len == 0 || j == len) ? "" : builder.substring(j);
final int start = offsetInPosition + i + j;
result.add(new AntDomDependentTargetReference(target, targetName, start));
i = rightBound + 1;
}
while (rightBound < valueLen);
return result;
}
finally {
StringBuilderSpinAllocator.dispose(builder);
}
}
finally {
PsiReferenceListSpinAllocator.dispose(result);
}
}
}