mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
added handling for available task when resolving properties (IDEADEV-40561)
Currently supporting conditions on files
This commit is contained in:
@@ -22,6 +22,7 @@ import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.PsiNamedElement;
|
||||
import com.intellij.psi.xml.XmlFile;
|
||||
import com.intellij.util.Processor;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -73,6 +74,8 @@ public interface AntFile extends PsiFile, AntElement, PsiNamedElement, Modificat
|
||||
@Nullable
|
||||
AntProperty getProperty(@NonNls final String name);
|
||||
|
||||
void processAllProperties(@NonNls final String name, Processor<AntProperty> processor);
|
||||
|
||||
void setProperty(final String name, final AntProperty element);
|
||||
|
||||
@NotNull
|
||||
|
||||
@@ -50,6 +50,7 @@ import com.intellij.psi.xml.XmlFile;
|
||||
import com.intellij.psi.xml.XmlTag;
|
||||
import com.intellij.util.Alarm;
|
||||
import com.intellij.util.LocalTimeCounter;
|
||||
import com.intellij.util.Processor;
|
||||
import com.intellij.util.StringBuilderSpinAllocator;
|
||||
import org.apache.tools.ant.Project;
|
||||
import org.apache.tools.ant.TaskContainer;
|
||||
@@ -101,7 +102,7 @@ public class AntFileImpl extends LightPsiFileBase implements AntFile {
|
||||
private ClassLoader myClassLoader;
|
||||
private Hashtable myProjectProperties;
|
||||
private boolean myNeedPropertiesRebuild = false;
|
||||
private Map<String, AntProperty> myProperties;
|
||||
private Map<String, List<AntProperty>> myProperties;
|
||||
private volatile AntProperty[] myPropertiesArray;
|
||||
private volatile PropertiesWatcher myDependentFilesWatcher;
|
||||
private List<String> myEnvPrefixes;
|
||||
@@ -219,7 +220,16 @@ public class AntFileImpl extends LightPsiFileBase implements AntFile {
|
||||
copy.myProjectElements = myProjectElements == null ? null : new HashMap<AntTypeId, String>(myProjectElements);
|
||||
copy.myClassLoader = myClassLoader;
|
||||
copy.myExternalProperties = myExternalProperties != null? new HashMap<String, String>(myExternalProperties) : null;
|
||||
copy.myProperties = myProperties != null? new HashMap<String, AntProperty>(myProperties) : null;
|
||||
if (myProperties != null) {
|
||||
final HashMap<String, List<AntProperty>> map = new HashMap<String, List<AntProperty>>();
|
||||
for (Map.Entry<String, List<AntProperty>> entry : myProperties.entrySet()) {
|
||||
map.put(entry.getKey(), new ArrayList<AntProperty>(entry.getValue()));
|
||||
}
|
||||
copy.myProperties = map;
|
||||
}
|
||||
else {
|
||||
copy.myProperties = null;
|
||||
}
|
||||
|
||||
return copy;
|
||||
}
|
||||
@@ -411,6 +421,10 @@ public class AntFileImpl extends LightPsiFileBase implements AntFile {
|
||||
return getPropertyRecursively(name, new HashSet<AntFile>());
|
||||
}
|
||||
|
||||
public void processAllProperties(@NonNls String name, Processor<AntProperty> processor) {
|
||||
processAllPropertiesRecursively(name, new HashSet<AntFile>(), processor);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private AntProperty getPropertyRecursively(final String name, final Set<AntFile> processed) {
|
||||
if (name == null || processed.contains(this)) {
|
||||
@@ -422,7 +436,13 @@ public class AntFileImpl extends LightPsiFileBase implements AntFile {
|
||||
AntProperty antProperty;
|
||||
|
||||
synchronized (PsiLock.LOCK) {
|
||||
antProperty = myProperties != null ? myProperties.get(name) : null;
|
||||
if (myProperties != null) {
|
||||
final List<AntProperty> antProperties = myProperties.get(name);
|
||||
antProperty = antProperties != null && !antProperties.isEmpty()? antProperties.get(0) : null;
|
||||
}
|
||||
else {
|
||||
antProperty = null;
|
||||
}
|
||||
}
|
||||
|
||||
if (antProperty == null) {
|
||||
@@ -444,6 +464,43 @@ public class AntFileImpl extends LightPsiFileBase implements AntFile {
|
||||
}
|
||||
}
|
||||
|
||||
private void processAllPropertiesRecursively(final String name, final Set<AntFile> processed, Processor<AntProperty> processor) {
|
||||
if (name == null || processed.contains(this)) {
|
||||
return;
|
||||
}
|
||||
processed.add(this);
|
||||
|
||||
try {
|
||||
synchronized (PsiLock.LOCK) {
|
||||
if (myProperties != null) {
|
||||
final List<AntProperty> antProperties = myProperties.get(name);
|
||||
if (antProperties != null) {
|
||||
for (AntProperty property : antProperties) {
|
||||
if (!processor.process(property)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
final AntProject antProject = getAntProject();
|
||||
if (antProject != null) {
|
||||
for (AntFile imported : antProject.getImportedFiles()) {
|
||||
if (imported instanceof AntFileImpl) {
|
||||
((AntFileImpl)imported).processAllPropertiesRecursively(name, processed, processor);
|
||||
}
|
||||
else {
|
||||
imported.processAllProperties(name, processor);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
finally {
|
||||
processed.remove(this);
|
||||
}
|
||||
}
|
||||
|
||||
public void buildPropertiesIfNeeded() {
|
||||
if (myNeedPropertiesRebuild || (myDependentFilesWatcher != null && myDependentFilesWatcher.needRebuildProperties())) {
|
||||
buildPropertiesMap();
|
||||
@@ -453,7 +510,7 @@ public class AntFileImpl extends LightPsiFileBase implements AntFile {
|
||||
private void buildPropertiesMap() {
|
||||
myNeedPropertiesRebuild = false;
|
||||
myDependentFilesWatcher = null;
|
||||
myProperties = new HashMap<String, AntProperty>();
|
||||
myProperties = new HashMap<String, List<AntProperty>>();
|
||||
myPropertiesArray = null;
|
||||
loadPredefinedProperties(myProjectProperties, myExternalProperties);
|
||||
final List<PsiFile> dependentFiles = PropertiesBuilder.defineProperties(this);
|
||||
@@ -577,7 +634,7 @@ public class AntFileImpl extends LightPsiFileBase implements AntFile {
|
||||
return super.getNavigationElement();
|
||||
}
|
||||
};
|
||||
myProperties.put(property.getName(), property);
|
||||
appendProperty(property.getName(), property);
|
||||
}
|
||||
}
|
||||
finally {
|
||||
@@ -591,17 +648,22 @@ public class AntFileImpl extends LightPsiFileBase implements AntFile {
|
||||
if (myNeedPropertiesRebuild) {
|
||||
buildPropertiesMap();
|
||||
}
|
||||
if (myProperties == null) {
|
||||
myProperties = new HashMap<String, AntProperty>();
|
||||
myPropertiesArray = null;
|
||||
}
|
||||
if (!myProperties.containsKey(name)) {
|
||||
myProperties.put(name, element);
|
||||
myPropertiesArray = null;
|
||||
}
|
||||
appendProperty(name, element);
|
||||
}
|
||||
}
|
||||
|
||||
private void appendProperty(String name, AntProperty element) {
|
||||
if (myProperties == null) {
|
||||
myProperties = new HashMap<String, List<AntProperty>>();
|
||||
}
|
||||
List<AntProperty> props = myProperties.get(name);
|
||||
if (props == null) {
|
||||
myProperties.put(name, props = new ArrayList<AntProperty>());
|
||||
}
|
||||
props.add(element);
|
||||
myPropertiesArray = null;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public AntProperty[] getProperties() {
|
||||
synchronized (PsiLock.LOCK) {
|
||||
@@ -612,7 +674,13 @@ public class AntFileImpl extends LightPsiFileBase implements AntFile {
|
||||
return AntProperty.EMPTY_ARRAY;
|
||||
}
|
||||
if (myPropertiesArray == null) {
|
||||
myPropertiesArray = myProperties.values().toArray(new AntProperty[myProperties.size()]);
|
||||
final List<AntProperty> props = new ArrayList<AntProperty>(myProperties.size());
|
||||
for (List<AntProperty> list : myProperties.values()) {
|
||||
if (!list.isEmpty()) {
|
||||
props.add(list.get(0));
|
||||
}
|
||||
}
|
||||
myPropertiesArray = props.toArray(new AntProperty[props.size()]);
|
||||
}
|
||||
return myPropertiesArray;
|
||||
}
|
||||
|
||||
@@ -26,10 +26,10 @@ import com.intellij.psi.PsiLock;
|
||||
import com.intellij.psi.xml.XmlAttribute;
|
||||
import com.intellij.psi.xml.XmlAttributeValue;
|
||||
import com.intellij.psi.xml.XmlTag;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import com.intellij.util.StringBuilderSpinAllocator;
|
||||
import com.intellij.util.StringSetSpinAllocator;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -42,6 +42,13 @@ import java.util.*;
|
||||
public class AntPropertyImpl extends AntTaskImpl implements AntProperty {
|
||||
|
||||
private PsiElement myPropertiesFile;
|
||||
private static final Set<String> ourPropertyDefiningTags = new HashSet<String>(Arrays.asList(
|
||||
AntFileImpl.PROPERTY,
|
||||
"param",
|
||||
"condition",
|
||||
"input",
|
||||
"available"
|
||||
));
|
||||
|
||||
public AntPropertyImpl(final AntElement parent,
|
||||
final XmlTag sourceElement,
|
||||
@@ -111,7 +118,7 @@ public class AntPropertyImpl extends AntTaskImpl implements AntProperty {
|
||||
synchronized (PsiLock.LOCK) {
|
||||
final XmlTag se = getSourceElement();
|
||||
final String tagName = se.getName();
|
||||
if (AntFileImpl.PROPERTY.equals(tagName) || "param".equals(tagName) || "condition".equals(tagName) || "input".equals(tagName)) { // todo: support conditions separately
|
||||
if (ourPropertyDefiningTags.contains(tagName)) { // todo: support conditions separately
|
||||
String value = getPropertyValue();
|
||||
if (value == null && propName != null) {
|
||||
final PropertiesFile propertiesFile = getPropertiesFile();
|
||||
@@ -241,6 +248,20 @@ public class AntPropertyImpl extends AntTaskImpl implements AntProperty {
|
||||
@Nullable
|
||||
private String getPropertyValue() {
|
||||
final XmlTag sourceElement = getSourceElement();
|
||||
final String tagName = sourceElement.getName();
|
||||
if ("available".equals(tagName)) {
|
||||
// check only 'file' tag because others could be examined only at runtime
|
||||
final String filePath = sourceElement.getAttributeValue("file");
|
||||
if (filePath != null) {
|
||||
final String _filePath = computeAttributeValue(filePath);
|
||||
if (_filePath != null) {
|
||||
if (!new File(_filePath).exists()) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
String value = sourceElement.getAttributeValue("value");
|
||||
if (value == null) {
|
||||
value = sourceElement.getAttributeValue("location");
|
||||
|
||||
@@ -24,6 +24,7 @@ import com.intellij.lang.ant.psi.introspection.AntTypeDefinition;
|
||||
import com.intellij.lang.ant.psi.introspection.AntTypeId;
|
||||
import com.intellij.lang.ant.psi.introspection.impl.AntTypeDefinitionImpl;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.util.Ref;
|
||||
import com.intellij.openapi.vfs.LocalFileSystem;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.PsiElement;
|
||||
@@ -33,10 +34,7 @@ import com.intellij.psi.xml.XmlAttribute;
|
||||
import com.intellij.psi.xml.XmlAttributeValue;
|
||||
import com.intellij.psi.xml.XmlElement;
|
||||
import com.intellij.psi.xml.XmlTag;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import com.intellij.util.SpinAllocator;
|
||||
import com.intellij.util.StringBuilderSpinAllocator;
|
||||
import com.intellij.util.StringSetSpinAllocator;
|
||||
import com.intellij.util.*;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -527,28 +525,37 @@ public class AntStructuredElementImpl extends AntElementImpl implements AntStruc
|
||||
continue;
|
||||
}
|
||||
final String prop = value.substring(startProp + 2, endProp);
|
||||
final AntProperty propElement = antFile.getProperty(prop);
|
||||
String resolvedValue = null;
|
||||
if (propElement != null) {
|
||||
resolvedValue = propElement.getValue(prop);
|
||||
if (resolvedValue != null) {
|
||||
if (elementStack.contains(new Pair<PsiElement, String>(propElement, resolvedValue))) {
|
||||
return value; // prevent cycles
|
||||
final Ref<String> resolvedValueRef = new Ref<String>(null);
|
||||
final Ref<Boolean> shouldReturnOriginalValue = new Ref<Boolean>(Boolean.FALSE);
|
||||
antFile.processAllProperties(prop, new Processor<AntProperty>() {
|
||||
public boolean process(AntProperty antProperty) {
|
||||
final String resolvedValue = antProperty.getValue(prop);
|
||||
if (resolvedValue == null) {
|
||||
return true;
|
||||
}
|
||||
resolvedValue = ((AntStructuredElementImpl)propElement).computeAttributeValue(resolvedValue, elementStack, antConfig);
|
||||
if (elementStack.contains(new Pair<PsiElement, String>(antProperty, resolvedValue))) {
|
||||
shouldReturnOriginalValue.set(Boolean.TRUE);
|
||||
}
|
||||
else {
|
||||
resolvedValueRef.set(((AntStructuredElementImpl)antProperty).computeAttributeValue(resolvedValue, elementStack, antConfig));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
});
|
||||
if (shouldReturnOriginalValue.get()) {
|
||||
return value; // prevent cycles
|
||||
}
|
||||
if (resolvedValue == null) {
|
||||
if (resolvedValueRef.get() == null) {
|
||||
startProp += 2;
|
||||
}
|
||||
else {
|
||||
if (resolvedValue.equals(value) /*prevent tail recursion*/) {
|
||||
if (resolvedValueRef.get().equals(value) /*prevent tail recursion*/) {
|
||||
return value;
|
||||
}
|
||||
final StringBuilder builder = StringBuilderSpinAllocator.alloc();
|
||||
try {
|
||||
builder.append(value, 0, startProp);
|
||||
builder.append(resolvedValue);
|
||||
builder.append(resolvedValueRef.get());
|
||||
if (endProp < value.length() - 1) {
|
||||
builder.append(value, endProp + 1, value.length());
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user