mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
param references in macrodefs supported
This commit is contained in:
@@ -0,0 +1,114 @@
|
||||
/*
|
||||
* 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.lookup.AutoCompletionPolicy;
|
||||
import com.intellij.codeInsight.lookup.LookupElement;
|
||||
import com.intellij.codeInsight.lookup.LookupElementBuilder;
|
||||
import com.intellij.lang.ant.AntBundle;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.pom.references.PomService;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiReference;
|
||||
import com.intellij.psi.impl.PsiManagerEx;
|
||||
import com.intellij.psi.impl.source.resolve.ResolveCache;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.xml.DomElement;
|
||||
import com.intellij.util.xml.DomTarget;
|
||||
import com.intellij.util.xml.DomUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Eugene Zhuravlev
|
||||
* Date: Aug 16, 2010
|
||||
*/
|
||||
public class AntDomMacrodefAttributeReference extends AntDomReferenceBase{
|
||||
|
||||
public AntDomMacrodefAttributeReference(PsiElement element, TextRange range) {
|
||||
super(element, range, true);
|
||||
}
|
||||
|
||||
public String getUnresolvedMessagePattern() {
|
||||
return AntBundle.message("unknown.macro.attribute", getCanonicalText());
|
||||
}
|
||||
|
||||
public PsiElement resolve() {
|
||||
return ((PsiManagerEx)getElement().getManager()).getResolveCache().resolveWithCaching(this, MyResolver.INSTANCE, false, false);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Object[] getVariants() {
|
||||
final AntDomMacroDef parentMacrodef = getParentMacrodef();
|
||||
if (parentMacrodef != null) {
|
||||
final List variants = new ArrayList();
|
||||
for (AntDomMacrodefAttribute attribute : parentMacrodef.getMacroAttributes()) {
|
||||
final String attribName = attribute.getName().getStringValue();
|
||||
if (attribName != null && attribName.length() > 0) {
|
||||
final LookupElementBuilder builder = LookupElementBuilder.create(attribName);
|
||||
final LookupElement element = AutoCompletionPolicy.GIVE_CHANCE_TO_OVERWRITE.applyPolicy(builder);
|
||||
variants.add(element);
|
||||
}
|
||||
}
|
||||
return ContainerUtil.toArray(variants, new Object[variants.size()]);
|
||||
}
|
||||
return EMPTY_ARRAY;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private AntDomMacroDef getParentMacrodef() {
|
||||
final PsiElement element = getElement();
|
||||
if (element == null) {
|
||||
return null;
|
||||
}
|
||||
final DomElement domElement = DomUtil.getDomElement(element);
|
||||
if (domElement == null) {
|
||||
return null;
|
||||
}
|
||||
return domElement.getParentOfType(AntDomMacroDef.class, false);
|
||||
}
|
||||
|
||||
private static class MyResolver implements ResolveCache.Resolver {
|
||||
|
||||
static final MyResolver INSTANCE = new MyResolver();
|
||||
|
||||
public PsiElement resolve(PsiReference psiReference, boolean incompleteCode) {
|
||||
final PsiElement element = psiReference.getElement();
|
||||
if (element == null) {
|
||||
return null;
|
||||
}
|
||||
final DomElement domElement = DomUtil.getDomElement(element);
|
||||
if (domElement == null) {
|
||||
return null;
|
||||
}
|
||||
final AntDomMacroDef macrodef = domElement.getParentOfType(AntDomMacroDef.class, false);
|
||||
if (macrodef == null) {
|
||||
return null;
|
||||
}
|
||||
final String name = AntStringResolver.computeString(domElement, psiReference.getCanonicalText());
|
||||
for (AntDomMacrodefAttribute attribute : macrodef.getMacroAttributes()) {
|
||||
if (name.equals(attribute.getName().getStringValue())) {
|
||||
final DomTarget target = DomTarget.getTarget(attribute);
|
||||
return target != null? PomService.convertToPsi(target) : null;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
package com.intellij.lang.ant.dom;
|
||||
|
||||
import com.intellij.lang.ant.misc.PsiReferenceListSpinAllocator;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.psi.ElementManipulators;
|
||||
import com.intellij.psi.PsiElement;
|
||||
@@ -22,13 +23,15 @@ import com.intellij.psi.PsiReference;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.psi.xml.XmlAttribute;
|
||||
import com.intellij.psi.xml.XmlAttributeValue;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.xml.ConvertContext;
|
||||
import com.intellij.util.xml.DomElement;
|
||||
import com.intellij.util.xml.DomReferenceInjector;
|
||||
import com.intellij.util.xml.DomUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@@ -48,14 +51,21 @@ class AntReferenceInjector implements DomReferenceInjector {
|
||||
@NotNull
|
||||
public PsiReference[] inject(@Nullable String unresolvedText, @NotNull PsiElement element, @NotNull ConvertContext context) {
|
||||
if (element instanceof XmlAttributeValue) {
|
||||
final List<PsiReference> refs = new ArrayList<PsiReference>();
|
||||
addPropertyReferences(context, (XmlAttributeValue)element, refs);
|
||||
return refs.toArray(new PsiReference[refs.size()]);
|
||||
final XmlAttributeValue xmlAttributeValue = (XmlAttributeValue)element;
|
||||
final List<PsiReference> refs = PsiReferenceListSpinAllocator.alloc();
|
||||
try {
|
||||
addPropertyReferences(context, xmlAttributeValue, refs);
|
||||
addMacrodefParameterRefs(xmlAttributeValue, refs);
|
||||
return refs.size() == 0? PsiReference.EMPTY_ARRAY : ContainerUtil.toArray(refs, new PsiReference[refs.size()]);
|
||||
}
|
||||
finally {
|
||||
PsiReferenceListSpinAllocator.dispose(refs);
|
||||
}
|
||||
}
|
||||
return PsiReference.EMPTY_ARRAY;
|
||||
}
|
||||
|
||||
private static void addPropertyReferences(@NotNull ConvertContext context, final XmlAttributeValue xmlAttributeValue, final List<PsiReference> result) {
|
||||
private static void addPropertyReferences(@NotNull ConvertContext context, final XmlAttributeValue xmlAttributeValue, final Collection<PsiReference> result) {
|
||||
final String value = xmlAttributeValue.getValue();
|
||||
final DomElement contextElement = context.getInvocationElement();
|
||||
|
||||
@@ -75,7 +85,7 @@ class AntReferenceInjector implements DomReferenceInjector {
|
||||
}
|
||||
}
|
||||
|
||||
if (xmlAttributeValue != null && value.indexOf("@{") < 0) {
|
||||
if (xmlAttributeValue != null /*&& value.indexOf("@{") < 0*/) {
|
||||
final int valueBeginingOffset = Math.abs(xmlAttributeValue.getTextRange().getStartOffset() - xmlAttributeValue.getValueTextRange().getStartOffset());
|
||||
int startIndex;
|
||||
int endIndex = -1;
|
||||
@@ -117,5 +127,45 @@ class AntReferenceInjector implements DomReferenceInjector {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void addMacrodefParameterRefs(@NotNull XmlAttributeValue element, final Collection<PsiReference> refs) {
|
||||
final DomElement domElement = DomUtil.getDomElement(element);
|
||||
if (domElement == null) {
|
||||
return;
|
||||
}
|
||||
final AntDomMacroDef macrodef = domElement.getParentOfType(AntDomMacroDef.class, true);
|
||||
if (macrodef == null) {
|
||||
return;
|
||||
}
|
||||
final String text = ElementManipulators.getValueText(element);
|
||||
final int valueBeginingOffset = Math.abs(element.getTextRange().getStartOffset() - element.getValueTextRange().getStartOffset());
|
||||
int startIndex;
|
||||
int endIndex = -1;
|
||||
while ((startIndex = text.indexOf("@{", endIndex + 1)) > endIndex) {
|
||||
startIndex += 2;
|
||||
endIndex = startIndex;
|
||||
int nestedBrackets = 0;
|
||||
while (text.length() > endIndex) {
|
||||
final char ch = text.charAt(endIndex);
|
||||
if (ch == '}') {
|
||||
if (nestedBrackets == 0) {
|
||||
break;
|
||||
}
|
||||
--nestedBrackets;
|
||||
}
|
||||
else if (ch == '{') {
|
||||
++nestedBrackets;
|
||||
}
|
||||
++endIndex;
|
||||
}
|
||||
if(nestedBrackets > 0 || endIndex == text.length()) return;
|
||||
if (endIndex >= startIndex) {
|
||||
//final String name = text.substring(startIndex, endIndex);
|
||||
refs.add(new AntDomMacrodefAttributeReference(element, new TextRange(valueBeginingOffset + startIndex, valueBeginingOffset + endIndex)));
|
||||
}
|
||||
endIndex = startIndex;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -15,13 +15,21 @@
|
||||
*/
|
||||
package com.intellij.lang.ant;
|
||||
|
||||
import com.intellij.lang.ant.config.AntConfigurationBase;
|
||||
import com.intellij.lang.ant.dom.AntDomMacrodefAttribute;
|
||||
import com.intellij.openapi.application.PluginPathManager;
|
||||
import com.intellij.openapi.util.SystemInfo;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.pom.PomTargetPsiElement;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.PsiReference;
|
||||
import com.intellij.psi.xml.XmlFile;
|
||||
import com.intellij.psi.xml.XmlTag;
|
||||
import com.intellij.testFramework.ResolveTestCase;
|
||||
import com.intellij.util.xml.DomElement;
|
||||
import com.intellij.util.xml.DomTarget;
|
||||
import com.intellij.util.xml.DomUtil;
|
||||
|
||||
public class AntResolveTest extends ResolveTestCase {
|
||||
|
||||
@@ -217,10 +225,15 @@ public class AntResolveTest extends ResolveTestCase {
|
||||
public void testBuildNumber() throws Exception {
|
||||
doPropertyTest();
|
||||
}
|
||||
// TODO: implement functionality
|
||||
public void _testPropertyInMacrodefParam() throws Exception {
|
||||
|
||||
public void testPropertyInMacrodefParam() throws Exception {
|
||||
PsiReference ref = configure();
|
||||
assertNotNull(ref.resolve());
|
||||
final PsiElement result = ref.resolve();
|
||||
assertTrue(result instanceof PomTargetPsiElement);
|
||||
final PsiElement naviElem = ((DomTarget)((PomTargetPsiElement)result).getTarget()).getNavigationElement();
|
||||
final DomElement domElement = DomUtil.getDomElement(naviElem);
|
||||
assertNotNull(domElement);
|
||||
assertNotNull(domElement.getParentOfType(AntDomMacrodefAttribute.class, false));
|
||||
}
|
||||
|
||||
public void testMacrodefElement() throws Exception {
|
||||
@@ -228,24 +241,28 @@ public class AntResolveTest extends ResolveTestCase {
|
||||
assertNotNull(ref.resolve());
|
||||
}
|
||||
|
||||
/* todo: rewrite into DOM
|
||||
public void testAntFilePropertyWithContexts() throws Exception {
|
||||
final AntPropertyReference refImporting = (AntPropertyReference)configureByFile("PropertyAntFileImporting.ant");
|
||||
final AntFile importing = refImporting.getElement().getAntFile();
|
||||
final PsiReference refImporting = configureByFile("PropertyAntFileImporting.ant");
|
||||
|
||||
final PsiFile importing = refImporting.getElement().getContainingFile();
|
||||
assertTrue(importing instanceof XmlFile);
|
||||
|
||||
final VirtualFile vFile = importing.getVirtualFile();
|
||||
assertTrue(vFile != null);
|
||||
|
||||
final AntPropertyReference refImported = (AntPropertyReference)configureByFile("PropertyAntFileImported.ant", vFile.getParent());
|
||||
final AntFile imported = refImported.getElement().getAntFile();
|
||||
|
||||
AntConfigurationBase.getInstance(getProject()).setContextFile(imported, importing);
|
||||
importing.clearCaches(); // need this because imported file was created after the importing
|
||||
final PsiReference refImported = configureByFile("PropertyAntFileImported.ant", vFile.getParent());
|
||||
|
||||
final PsiFile imported = refImported.getElement().getContainingFile();
|
||||
assertTrue(imported instanceof XmlFile);
|
||||
|
||||
final VirtualFile importedVFile = imported.getVirtualFile();
|
||||
assertTrue(importedVFile != null);
|
||||
|
||||
AntConfigurationBase.getInstance(getProject()).setContextFile((XmlFile)imported, (XmlFile)importing);
|
||||
|
||||
assertTrue(refImported.resolve() != null);
|
||||
assertTrue(refImporting.resolve() != null);
|
||||
}
|
||||
*/
|
||||
|
||||
private void doTargetTest() throws Exception {
|
||||
PsiReference ref = configure();
|
||||
|
||||
@@ -161,6 +161,7 @@ nested.element.is.not.allowed.here=Nested element ''{0}'' is not allowed here
|
||||
cannot.resolve.target=Target ''{0}'' is unknown
|
||||
cannot.resolve.refid=Cannot resolve ''{0}'' refid
|
||||
unknown.property=Property ''{0}'' is unknown
|
||||
unknown.macro.attribute=Macro attribute ''{0}'' is unknown
|
||||
file.doesnt.exist=''{0}'' does not exist
|
||||
integer.attribute.has.invalid.value=Attribute ''{0}'' should have an integer value
|
||||
intention.create.target.family.name=Create target
|
||||
|
||||
Reference in New Issue
Block a user