mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
1. path-like structures support
2. documentation provider for ant's dom
This commit is contained in:
@@ -0,0 +1,285 @@
|
||||
/*
|
||||
* 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.doc;
|
||||
|
||||
import com.intellij.lang.ant.AntSupport;
|
||||
import com.intellij.lang.ant.config.impl.AntInstallation;
|
||||
import com.intellij.lang.ant.dom.AntDomElement;
|
||||
import com.intellij.lang.ant.dom.AntDomProject;
|
||||
import com.intellij.lang.ant.dom.AntDomTarget;
|
||||
import com.intellij.lang.ant.psi.AntFilesProvider;
|
||||
import com.intellij.lang.documentation.DocumentationProvider;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.vfs.*;
|
||||
import com.intellij.pom.PomTarget;
|
||||
import com.intellij.pom.PomTargetPsiElement;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.PsiManager;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.psi.xml.XmlElement;
|
||||
import com.intellij.psi.xml.XmlTag;
|
||||
import com.intellij.util.StringBuilderSpinAllocator;
|
||||
import com.intellij.util.xml.DomElement;
|
||||
import com.intellij.util.xml.DomTarget;
|
||||
import com.intellij.util.xml.reflect.DomChildrenDescription;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
|
||||
public class AntDomDocumentationProvider implements DocumentationProvider {
|
||||
|
||||
public String generateDoc(PsiElement element, PsiElement originalElement) {
|
||||
final String mainDoc = getMainDocumentation(originalElement);
|
||||
final String additionalDoc = getAdditionalDocumentation(originalElement);
|
||||
if (mainDoc == null && additionalDoc == null) {
|
||||
return null;
|
||||
}
|
||||
final StringBuilder builder = StringBuilderSpinAllocator.alloc();
|
||||
try {
|
||||
if (additionalDoc != null) {
|
||||
builder.append(additionalDoc);
|
||||
}
|
||||
if (mainDoc != null) {
|
||||
builder.append(mainDoc);
|
||||
}
|
||||
return builder.toString();
|
||||
}
|
||||
finally {
|
||||
StringBuilderSpinAllocator.dispose(builder);
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static String getMainDocumentation(PsiElement elem) {
|
||||
final VirtualFile helpFile = getHelpFile(elem);
|
||||
if (helpFile != null) {
|
||||
try {
|
||||
return VfsUtil.loadText(helpFile);
|
||||
}
|
||||
catch (IOException ignored) {
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static String getAdditionalDocumentation(PsiElement elem) {
|
||||
final XmlTag xmlTag = PsiTreeUtil.getParentOfType(elem, XmlTag.class);
|
||||
if (xmlTag == null) {
|
||||
return null;
|
||||
}
|
||||
final AntDomElement antElement = AntSupport.getAntDomElement(xmlTag);
|
||||
if (antElement instanceof AntFilesProvider) {
|
||||
final List<File> list = ((AntFilesProvider)antElement).getFiles(new HashSet<AntFilesProvider>());
|
||||
if (list.size() > 0) {
|
||||
final @NonNls StringBuilder builder = StringBuilderSpinAllocator.alloc();
|
||||
try {
|
||||
final XmlTag tag = antElement.getXmlTag();
|
||||
if (tag != null) {
|
||||
builder.append("<b>");
|
||||
builder.append(tag.getName());
|
||||
builder.append(":</b>");
|
||||
}
|
||||
for (File file : list) {
|
||||
if (builder.length() > 0) {
|
||||
builder.append("<br>");
|
||||
}
|
||||
builder.append(file.getPath());
|
||||
}
|
||||
return builder.toString();
|
||||
}
|
||||
finally {
|
||||
StringBuilderSpinAllocator.dispose(builder);
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static VirtualFile getHelpFile(final PsiElement element) {
|
||||
final XmlTag xmlTag = PsiTreeUtil.getParentOfType(element, XmlTag.class);
|
||||
if (xmlTag == null) {
|
||||
return null;
|
||||
}
|
||||
final AntDomElement antElement = AntSupport.getAntDomElement(xmlTag);
|
||||
if (antElement == null) {
|
||||
return null;
|
||||
}
|
||||
final AntDomProject antProject = antElement.getAntProject();
|
||||
if (antProject == null) {
|
||||
return null;
|
||||
}
|
||||
final AntInstallation installation = antProject.getAntInstallation();
|
||||
if (installation == null) {
|
||||
return null; // not configured properly and bundled installation missing
|
||||
}
|
||||
final String antHomeDir = AntInstallation.HOME_DIR.get(installation.getProperties());
|
||||
|
||||
if (antHomeDir == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@NonNls String path = antHomeDir + "/docs/manual";
|
||||
String url;
|
||||
if (new File(path).exists()) {
|
||||
url = VirtualFileManager.constructUrl(LocalFileSystem.PROTOCOL, FileUtil.toSystemIndependentName(path));
|
||||
}
|
||||
else {
|
||||
path = antHomeDir + "/docs.zip";
|
||||
if (new File(path).exists()) {
|
||||
url = VirtualFileManager.constructUrl(JarFileSystem.PROTOCOL, FileUtil.toSystemIndependentName(path) + JarFileSystem.JAR_SEPARATOR + "docs/manual");
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
final VirtualFile documentationRoot = VirtualFileManager.getInstance().findFileByUrl(url);
|
||||
if (documentationRoot == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return getHelpFile(antElement, documentationRoot);
|
||||
}
|
||||
|
||||
@NonNls private static final String CORE_TASKS_FOLDER_NAME = "CoreTasks";
|
||||
@NonNls private static final String CORE_TYPES_FOLDER_NAME = "CoreTypes";
|
||||
@NonNls private static final String OPTIONAL_TYPES_FOLDER_NAME = "OptionalTypes";
|
||||
@NonNls private static final String OPTIONAL_TASKS_FOLDER_NAME = "OptionalTasks";
|
||||
|
||||
@Nullable
|
||||
private static VirtualFile getHelpFile(AntDomElement antElement, final VirtualFile documentationRoot) {
|
||||
final XmlTag xmlTag = antElement.getXmlTag();
|
||||
if (xmlTag == null) {
|
||||
return null;
|
||||
}
|
||||
@NonNls final String helpFileShortName = "/" + xmlTag.getName() + ".html";
|
||||
|
||||
VirtualFile candidateHelpFile = documentationRoot.findFileByRelativePath(CORE_TASKS_FOLDER_NAME + helpFileShortName);
|
||||
if (candidateHelpFile != null) {
|
||||
return candidateHelpFile;
|
||||
}
|
||||
|
||||
candidateHelpFile = documentationRoot.findFileByRelativePath(OPTIONAL_TASKS_FOLDER_NAME + helpFileShortName);
|
||||
if (candidateHelpFile != null) {
|
||||
return candidateHelpFile;
|
||||
}
|
||||
|
||||
candidateHelpFile = documentationRoot.findFileByRelativePath(CORE_TYPES_FOLDER_NAME + helpFileShortName);
|
||||
if (candidateHelpFile != null) {
|
||||
return candidateHelpFile;
|
||||
}
|
||||
|
||||
candidateHelpFile = documentationRoot.findFileByRelativePath(OPTIONAL_TYPES_FOLDER_NAME + helpFileShortName);
|
||||
if (candidateHelpFile != null) {
|
||||
return candidateHelpFile;
|
||||
}
|
||||
|
||||
if(antElement instanceof AntDomTarget|| antElement instanceof AntDomProject) {
|
||||
candidateHelpFile = documentationRoot.findFileByRelativePath("using.html");
|
||||
if (candidateHelpFile != null) {
|
||||
return candidateHelpFile;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getQuickNavigateInfo(PsiElement element) { // todo!
|
||||
if (element instanceof PomTargetPsiElement) {
|
||||
final PomTarget pomTarget = ((PomTargetPsiElement)element).getTarget();
|
||||
if (pomTarget instanceof DomTarget) {
|
||||
final DomElement domElement = ((DomTarget)pomTarget).getDomElement();
|
||||
if (domElement instanceof AntDomTarget) {
|
||||
final AntDomTarget antTarget = (AntDomTarget)domElement;
|
||||
final String description = antTarget.getDescription().getRawText();
|
||||
if (description != null && description.length() > 0) {
|
||||
final String targetName = antTarget.getName().getRawText();
|
||||
final StringBuilder builder = StringBuilderSpinAllocator.alloc();
|
||||
try {
|
||||
builder.append("Target");
|
||||
if (targetName != null) {
|
||||
builder.append(" \"").append(targetName).append("\"");
|
||||
}
|
||||
final XmlElement xmlElement = antTarget.getXmlElement();
|
||||
if (xmlElement != null) {
|
||||
final PsiFile containingFile = xmlElement.getContainingFile();
|
||||
if (containingFile != null) {
|
||||
final String fileName = containingFile.getName();
|
||||
builder.append(" [").append(fileName).append("]");
|
||||
}
|
||||
}
|
||||
return builder.append(" ").append(description).toString();
|
||||
}
|
||||
finally {
|
||||
StringBuilderSpinAllocator.dispose(builder);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (pomTarget instanceof DomChildrenDescription) {
|
||||
final DomChildrenDescription description = (DomChildrenDescription)pomTarget;
|
||||
final Type type = description.getType();
|
||||
if (type instanceof Class && AntDomElement.class.isAssignableFrom(((Class)type))) {
|
||||
final String elemName = description.getName();
|
||||
if (elemName != null) {
|
||||
final AntDomElement.Role role = description.getUserData(AntDomElement.ROLE);
|
||||
final StringBuilder builder = StringBuilderSpinAllocator.alloc();
|
||||
try {
|
||||
if (role == AntDomElement.Role.TASK) {
|
||||
builder.append("Task ");
|
||||
}
|
||||
else if (role == AntDomElement.Role.DATA_TYPE) {
|
||||
builder.append("Data structure ");
|
||||
}
|
||||
builder.append(elemName);
|
||||
return builder.toString();
|
||||
}
|
||||
finally {
|
||||
StringBuilderSpinAllocator.dispose(builder);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public List<String> getUrlFor(PsiElement element, PsiElement originalElement) {
|
||||
final VirtualFile helpFile = getHelpFile(originalElement);
|
||||
if (helpFile == null || !(helpFile.getFileSystem() instanceof LocalFileSystem)) {
|
||||
return null;
|
||||
}
|
||||
return Collections.singletonList(helpFile.getUrl());
|
||||
}
|
||||
|
||||
public PsiElement getDocumentationElementForLookupItem(PsiManager psiManager, Object object, PsiElement element) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public PsiElement getDocumentationElementForLink(PsiManager psiManager, String link, PsiElement context) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -16,9 +16,16 @@
|
||||
package com.intellij.lang.ant.dom;
|
||||
|
||||
import com.intellij.lang.ant.psi.AntFilesProvider;
|
||||
import com.intellij.psi.PsiFileSystemItem;
|
||||
import com.intellij.util.StringBuilderSpinAllocator;
|
||||
import com.intellij.util.xml.Attribute;
|
||||
import com.intellij.util.xml.Convert;
|
||||
import com.intellij.util.xml.GenericAttributeValue;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
@@ -28,8 +35,78 @@ import java.util.Set;
|
||||
* Date: Jun 22, 2010
|
||||
*/
|
||||
public abstract class AntDomDirSet extends AntDomFilesProviderImpl{
|
||||
|
||||
@Attribute("dir")
|
||||
@Convert(value = AntPathConverter.class)
|
||||
public abstract GenericAttributeValue<PsiFileSystemItem> getDir();
|
||||
|
||||
@Attribute("file")
|
||||
@Convert(value = AntPathConverter.class)
|
||||
public abstract GenericAttributeValue<PsiFileSystemItem> getFile();
|
||||
|
||||
@NotNull
|
||||
public List<File> getFiles(Set<AntFilesProvider> processed) {
|
||||
return Collections.emptyList(); // todo
|
||||
protected List<File> getFiles(@Nullable AntDomPattern pattern, Set<AntFilesProvider> processed) {
|
||||
assert pattern != null;
|
||||
final File singleFile = getCanonicalFile(getFile().getStringValue());
|
||||
if (singleFile == null || pattern.hasIncludePatterns()) {
|
||||
// if singleFile is specified, there are no implicit includes
|
||||
final File root = getCanonicalFile(getDir().getStringValue());
|
||||
if (root != null) {
|
||||
final ArrayList<File> files = new ArrayList<File>();
|
||||
if (singleFile != null && singleFile.isDirectory()) {
|
||||
files.add(singleFile);
|
||||
}
|
||||
new FilesCollector().collectFiles(files, root, "", pattern);
|
||||
return files;
|
||||
}
|
||||
}
|
||||
|
||||
if (singleFile != null && singleFile.isDirectory()) {
|
||||
Collections.singletonList(singleFile);
|
||||
}
|
||||
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
|
||||
private static class FilesCollector {
|
||||
private static final int MAX_DIRS_TO_PROCESS = 100;
|
||||
private int myDirsProcessed = 0;
|
||||
|
||||
public void collectFiles(List<File> container, File from, String relativePath, final AntDomPattern pattern) {
|
||||
if (myDirsProcessed > MAX_DIRS_TO_PROCESS) {
|
||||
return;
|
||||
}
|
||||
myDirsProcessed++;
|
||||
final File[] children = from.listFiles();
|
||||
if (children != null) {
|
||||
for (File child : children) {
|
||||
if (child.isDirectory()) {
|
||||
final String childPath = makePath(relativePath, child.getName());
|
||||
if (pattern.acceptPath(childPath)) {
|
||||
container.add(child);
|
||||
}
|
||||
if (pattern.couldBeIncluded(childPath)) {
|
||||
collectFiles(container, child, childPath, pattern);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static String makePath(final String parentPath, final String name) {
|
||||
if (parentPath.length() == 0) {
|
||||
return name;
|
||||
}
|
||||
final StringBuilder builder = StringBuilderSpinAllocator.alloc();
|
||||
try {
|
||||
return builder.append(parentPath).append("/").append(name).toString();
|
||||
}
|
||||
finally {
|
||||
StringBuilderSpinAllocator.dispose(builder);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
package com.intellij.lang.ant.dom;
|
||||
|
||||
import com.intellij.openapi.util.Key;
|
||||
import com.intellij.psi.xml.XmlTag;
|
||||
import com.intellij.util.xml.*;
|
||||
|
||||
@@ -26,6 +27,10 @@ import java.util.List;
|
||||
*/
|
||||
@SuppressWarnings({"AbstractClassNeverImplemented"})
|
||||
public abstract class AntDomElement implements DomElement {
|
||||
public static enum Role {
|
||||
TASK, DATA_TYPE
|
||||
}
|
||||
public static final Key<Role> ROLE = Key.create("element_role");
|
||||
|
||||
@Attribute("id")
|
||||
public abstract GenericAttributeValue<String> getId();
|
||||
|
||||
@@ -28,13 +28,14 @@ import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Enumeration;
|
||||
import java.util.Map;
|
||||
import java.util.Hashtable;
|
||||
|
||||
/**
|
||||
* @author Eugene Zhuravlev
|
||||
* Date: Apr 9, 2010
|
||||
*/
|
||||
public class AntDomExtender extends DomExtender<AntDomElement>{
|
||||
|
||||
public void registerExtensions(@NotNull AntDomElement antDomElement, @NotNull DomExtensionsRegistrar registrar) {
|
||||
final XmlElement xmlElement = antDomElement.getXmlElement();
|
||||
if (xmlElement instanceof XmlTag) {
|
||||
@@ -45,6 +46,8 @@ public class AntDomExtender extends DomExtender<AntDomElement>{
|
||||
|
||||
final DomGenericInfo genericInfo = antDomElement.getGenericInfo();
|
||||
AntIntrospector parentElementIntrospector = null;
|
||||
final Hashtable<String,Class> taskDefs = reflected.getTaskDefinitions();
|
||||
final Hashtable<String, Class> dataTypeDefs = reflected.getDataTypeDefinitions();
|
||||
if ("project".equals(tagName)) {
|
||||
parentElementIntrospector = getIntrospector(reflected.getProject().getClass());
|
||||
}
|
||||
@@ -52,14 +55,12 @@ public class AntDomExtender extends DomExtender<AntDomElement>{
|
||||
parentElementIntrospector = getIntrospector(reflected.getTargetClass());
|
||||
}
|
||||
else {
|
||||
final Map<String, Class> tasks = reflected.getTaskDefinitions();
|
||||
final Class taskClass = tasks.get(tagName);
|
||||
final Class taskClass = taskDefs.get(tagName);
|
||||
if (taskClass != null) {
|
||||
parentElementIntrospector = getIntrospector(taskClass);
|
||||
}
|
||||
else {
|
||||
final Map<String, Class> dataTypes = reflected.getDataTypeDefinitions();
|
||||
final Class dataClass = dataTypes.get(tagName);
|
||||
final Class dataClass = dataTypeDefs.get(tagName);
|
||||
if (dataClass != null) {
|
||||
parentElementIntrospector = getIntrospector(dataClass);
|
||||
}
|
||||
@@ -67,7 +68,6 @@ public class AntDomExtender extends DomExtender<AntDomElement>{
|
||||
}
|
||||
|
||||
if (parentElementIntrospector != null) {
|
||||
|
||||
final Enumeration attributes = parentElementIntrospector.getAttributes();
|
||||
while (attributes.hasMoreElements()) {
|
||||
registerAttribute(registrar, genericInfo, (String)attributes.nextElement());
|
||||
@@ -75,17 +75,36 @@ public class AntDomExtender extends DomExtender<AntDomElement>{
|
||||
|
||||
// todo: handle custom tasks registered in typedefs
|
||||
if ("project".equals(tagName) || parentElementIntrospector.isContainer()) { // can contain any task or/and type definition
|
||||
for (Object nestedName : reflected.getTaskDefinitions().keySet()) {
|
||||
registerChild(registrar, genericInfo, (String)nestedName);
|
||||
for (String nestedName : taskDefs.keySet()) {
|
||||
final DomExtension extension = registerChild(registrar, genericInfo, nestedName);
|
||||
if (extension != null) {
|
||||
extension.putUserData(AntDomElement.ROLE, AntDomElement.Role.TASK);
|
||||
}
|
||||
}
|
||||
for (Object nestedTypeDef : reflected.getDataTypeDefinitions().keySet()) {
|
||||
registerChild(registrar, genericInfo, (String)nestedTypeDef);
|
||||
for (String nestedTypeDef : dataTypeDefs.keySet()) {
|
||||
final DomExtension extension = registerChild(registrar, genericInfo, nestedTypeDef);
|
||||
if (extension != null) {
|
||||
extension.putUserData(AntDomElement.ROLE, AntDomElement.Role.DATA_TYPE);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
final Enumeration<String> nested = parentElementIntrospector.getNestedElements();
|
||||
while (nested.hasMoreElements()) {
|
||||
registerChild(registrar, genericInfo, nested.nextElement());
|
||||
final String nestedElementName = nested.nextElement();
|
||||
final DomExtension extension = registerChild(registrar, genericInfo, nestedElementName);
|
||||
if (extension != null) {
|
||||
AntDomElement.Role role = null;
|
||||
if (taskDefs.containsKey(nestedElementName)) {
|
||||
role = AntDomElement.Role.TASK;
|
||||
}
|
||||
else if (dataTypeDefs.containsKey(nestedElementName)) {
|
||||
role = AntDomElement.Role.DATA_TYPE;
|
||||
}
|
||||
if (role != null) {
|
||||
extension.putUserData(AntDomElement.ROLE, role);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,9 +16,17 @@
|
||||
package com.intellij.lang.ant.dom;
|
||||
|
||||
import com.intellij.lang.ant.psi.AntFilesProvider;
|
||||
import com.intellij.psi.PsiFileSystemItem;
|
||||
import com.intellij.util.text.StringTokenizer;
|
||||
import com.intellij.util.xml.Attribute;
|
||||
import com.intellij.util.xml.Convert;
|
||||
import com.intellij.util.xml.GenericAttributeValue;
|
||||
import com.intellij.util.xml.SubTagList;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
@@ -28,8 +36,46 @@ import java.util.Set;
|
||||
* Date: Jun 22, 2010
|
||||
*/
|
||||
public abstract class AntDomFileList extends AntDomFilesProviderImpl{
|
||||
|
||||
@Attribute("dir")
|
||||
@Convert(value = AntPathConverter.class)
|
||||
public abstract GenericAttributeValue<PsiFileSystemItem> getDir();
|
||||
|
||||
@Attribute("files")
|
||||
public abstract GenericAttributeValue<String> getFilesString();
|
||||
|
||||
@SubTagList("file")
|
||||
public abstract List<AntDomNamedElement> getFiles(); // todo: add filename completion relative to the filelist's basedir
|
||||
|
||||
|
||||
@Nullable
|
||||
protected AntDomPattern getAntPattern() {
|
||||
return null; // not available for this data type
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public List<File> getFiles(Set<AntFilesProvider> processed) {
|
||||
return Collections.emptyList(); // todo
|
||||
protected List<File> getFiles(@Nullable AntDomPattern pattern, Set<AntFilesProvider> processed) {
|
||||
final File root = getCanonicalFile(getDir().getStringValue());
|
||||
if (root == null) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
final ArrayList<File> files = new ArrayList<File>();
|
||||
|
||||
final String filenames = getFilesString().getStringValue();
|
||||
if (filenames != null) {
|
||||
final StringTokenizer tokenizer = new StringTokenizer(filenames, ", \t\n\r\f", false);
|
||||
while (tokenizer.hasMoreTokens()) {
|
||||
files.add(new File(root, tokenizer.nextToken()));
|
||||
}
|
||||
}
|
||||
|
||||
for (AntDomNamedElement child : getFiles()) {
|
||||
final String fileName = child.getName().getStringValue();
|
||||
if (fileName != null) {
|
||||
files.add(new File(root, fileName));
|
||||
}
|
||||
}
|
||||
return files;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,9 +16,16 @@
|
||||
package com.intellij.lang.ant.dom;
|
||||
|
||||
import com.intellij.lang.ant.psi.AntFilesProvider;
|
||||
import com.intellij.psi.PsiFileSystemItem;
|
||||
import com.intellij.util.StringBuilderSpinAllocator;
|
||||
import com.intellij.util.xml.Attribute;
|
||||
import com.intellij.util.xml.Convert;
|
||||
import com.intellij.util.xml.GenericAttributeValue;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
@@ -28,8 +35,78 @@ import java.util.Set;
|
||||
* Date: Jun 22, 2010
|
||||
*/
|
||||
public abstract class AntDomFileSet extends AntDomFilesProviderImpl{
|
||||
@NotNull
|
||||
public List<File> getFiles(Set<AntFilesProvider> processed) {
|
||||
return Collections.emptyList(); // todo
|
||||
@Attribute("dir")
|
||||
@Convert(value = AntPathConverter.class)
|
||||
public abstract GenericAttributeValue<PsiFileSystemItem> getDir();
|
||||
|
||||
@Attribute("file")
|
||||
@Convert(value = AntPathConverter.class)
|
||||
public abstract GenericAttributeValue<PsiFileSystemItem> getFile();
|
||||
|
||||
@NotNull protected List<File> getFiles(@Nullable AntDomPattern pattern, Set<AntFilesProvider> processed) {
|
||||
assert pattern != null;
|
||||
final File singleFile = getCanonicalFile(getFile().getStringValue());
|
||||
if (singleFile == null || pattern.hasIncludePatterns()) {
|
||||
// if singleFile is specified, there are no implicit includes
|
||||
final File root = getCanonicalFile(getDir().getStringValue());
|
||||
if (root != null) {
|
||||
final ArrayList<File> files = new ArrayList<File>();
|
||||
if (singleFile != null) {
|
||||
files.add(singleFile);
|
||||
}
|
||||
new FilesCollector().collectFiles(files, root, "", pattern);
|
||||
return files;
|
||||
}
|
||||
}
|
||||
if (singleFile != null) {
|
||||
return Collections.singletonList(singleFile);
|
||||
}
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
private static class FilesCollector {
|
||||
private static final int MAX_DIRS_TO_PROCESS = 100;
|
||||
private int myDirsProcessed = 0;
|
||||
private boolean myDirCheckEnabled = false;
|
||||
|
||||
public void collectFiles(List<File> container, File from, String relativePath, final AntDomPattern pattern) {
|
||||
if (myDirsProcessed > MAX_DIRS_TO_PROCESS) {
|
||||
return;
|
||||
}
|
||||
final File[] children = from.listFiles();
|
||||
if (children != null && children.length > 0) {
|
||||
if (myDirCheckEnabled) {
|
||||
if (!pattern.couldBeIncluded(relativePath)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
else {
|
||||
myDirCheckEnabled = true;
|
||||
}
|
||||
myDirsProcessed++;
|
||||
for (File child : children) {
|
||||
final String childPath = makePath(relativePath, child.getName());
|
||||
if (pattern.acceptPath(childPath)) {
|
||||
container.add(child);
|
||||
}
|
||||
collectFiles(container, child, childPath, pattern);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static String makePath(final String parentPath, final String name) {
|
||||
if (parentPath.length() == 0) {
|
||||
return name;
|
||||
}
|
||||
final StringBuilder builder = StringBuilderSpinAllocator.alloc();
|
||||
try {
|
||||
return builder.append(parentPath).append("/").append(name).toString();
|
||||
}
|
||||
finally {
|
||||
StringBuilderSpinAllocator.dispose(builder);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -16,9 +16,14 @@
|
||||
package com.intellij.lang.ant.dom;
|
||||
|
||||
import com.intellij.lang.ant.psi.AntFilesProvider;
|
||||
import com.intellij.util.xml.Attribute;
|
||||
import com.intellij.util.xml.GenericAttributeValue;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
@@ -28,8 +33,81 @@ import java.util.Set;
|
||||
* Date: Jun 22, 2010
|
||||
*/
|
||||
public abstract class AntDomFilesProviderImpl extends AntDomElement implements AntFilesProvider{
|
||||
private volatile List<File> myCachedFiles;
|
||||
|
||||
@Attribute("defaultexcludes")
|
||||
public abstract GenericAttributeValue<String> getDefaultExcludes();
|
||||
@Attribute("casesensitive")
|
||||
public abstract GenericAttributeValue<String> getCaseSensitive();
|
||||
|
||||
|
||||
@NotNull
|
||||
public List<File> getFiles(Set<AntFilesProvider> processed) {
|
||||
public final List<File> getFiles(Set<AntFilesProvider> processed) {
|
||||
if (processed.contains(this)) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
List<File> result = myCachedFiles;
|
||||
if (result == null) {
|
||||
myCachedFiles = result = getFilesImpl(processed);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private List<File> getFilesImpl(final Set<AntFilesProvider> processed) {
|
||||
processed.add(this);
|
||||
try {
|
||||
final AntDomElement referenced = getRefId().getValue();
|
||||
if (referenced instanceof AntFilesProvider) {
|
||||
return ((AntFilesProvider)referenced).getFiles(processed);
|
||||
}
|
||||
return getFiles(getAntPattern(), processed);
|
||||
}
|
||||
finally {
|
||||
processed.remove(this);
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
protected AntDomPattern getAntPattern() {
|
||||
return AntDomPattern.create(this, shouldHonorDefaultExcludes(), matchPatternsCaseSensitive());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
protected List<File> getFiles(@Nullable AntDomPattern pattern, final Set<AntFilesProvider> processed) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
|
||||
private boolean shouldHonorDefaultExcludes() {
|
||||
@NonNls final String value = getDefaultExcludes().getRawText();
|
||||
return value == null || value.equalsIgnoreCase("yes") || value.equalsIgnoreCase("true");
|
||||
}
|
||||
|
||||
private boolean matchPatternsCaseSensitive() {
|
||||
@NonNls final String value = getCaseSensitive().getRawText();
|
||||
return value == null || value.equalsIgnoreCase("yes") || value.equalsIgnoreCase("true");
|
||||
}
|
||||
|
||||
@Nullable
|
||||
protected File getCanonicalFile(final String path) {
|
||||
if (path == null) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
final File file = new File(path);
|
||||
if (file.isAbsolute()) {
|
||||
return file.getCanonicalFile();
|
||||
}
|
||||
// todo: context project for basedir resolution?
|
||||
final String baseDir = getAntProject().getProjectBasedirPath();
|
||||
if (baseDir == null) {
|
||||
return null;
|
||||
}
|
||||
return new File(baseDir, path).getCanonicalFile();
|
||||
}
|
||||
catch (IOException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -16,10 +16,16 @@
|
||||
package com.intellij.lang.ant.dom;
|
||||
|
||||
import com.intellij.lang.ant.psi.AntFilesProvider;
|
||||
import com.intellij.psi.PsiFileSystemItem;
|
||||
import com.intellij.util.xml.Attribute;
|
||||
import com.intellij.util.xml.Convert;
|
||||
import com.intellij.util.xml.GenericAttributeValue;
|
||||
import org.apache.tools.ant.PathTokenizer;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Collections;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
@@ -28,8 +34,52 @@ import java.util.Set;
|
||||
* Date: Jun 22, 2010
|
||||
*/
|
||||
public abstract class AntDomPath extends AntDomFilesProviderImpl{
|
||||
@NotNull
|
||||
public List<File> getFiles(Set<AntFilesProvider> processed) {
|
||||
return Collections.emptyList(); // todo
|
||||
|
||||
@Attribute("location")
|
||||
@Convert(value = AntPathConverter.class)
|
||||
public abstract GenericAttributeValue<PsiFileSystemItem> getLocation();
|
||||
|
||||
@Attribute("path")
|
||||
@Convert(value = AntPathConverter.class)
|
||||
public abstract GenericAttributeValue<PsiFileSystemItem> getPath();
|
||||
|
||||
@Nullable
|
||||
protected AntDomPattern getAntPattern() {
|
||||
return null; // not available
|
||||
}
|
||||
|
||||
@NotNull protected List<File> getFiles(AntDomPattern pattern, Set<AntFilesProvider> processed) {
|
||||
final List<File> files = new ArrayList<File>();
|
||||
final File baseDir = getCanonicalFile(".");
|
||||
|
||||
addLocation(baseDir, files, getLocation().getStringValue());
|
||||
|
||||
final String pathString = getPath().getStringValue();
|
||||
if (pathString != null) {
|
||||
final PathTokenizer tokenizer = new PathTokenizer(pathString);
|
||||
while (tokenizer.hasMoreTokens()) {
|
||||
addLocation(baseDir, files, tokenizer.nextToken());
|
||||
}
|
||||
}
|
||||
|
||||
for (AntDomElement child : getAntChildren()) {
|
||||
if (child instanceof AntFilesProvider) {
|
||||
files.addAll(((AntFilesProvider)child).getFiles(processed));
|
||||
}
|
||||
}
|
||||
return files;
|
||||
}
|
||||
|
||||
|
||||
private static void addLocation(final File baseDir, final List<File> files, final String locationPath) {
|
||||
if (locationPath != null) {
|
||||
File file = new File(locationPath);
|
||||
if (file.isAbsolute()) {
|
||||
files.add(file);
|
||||
}
|
||||
else {
|
||||
files.add(new File(baseDir, locationPath));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -137,7 +137,7 @@ public abstract class AntDomProject extends AntDomNamedElement implements Proper
|
||||
return myClassLoader;
|
||||
}
|
||||
|
||||
private AntInstallation getAntInstallation() {
|
||||
public AntInstallation getAntInstallation() {
|
||||
final AntConfigurationBase configuration = AntConfigurationBase.getInstance(getXmlTag().getProject());
|
||||
AntInstallation antInstallation = null;
|
||||
if (configuration != null) {
|
||||
|
||||
@@ -32,6 +32,9 @@ public abstract class AntDomTarget extends AntDomNamedElement{
|
||||
@Attribute("unless")
|
||||
public abstract GenericAttributeValue<String> getUnlessPropertyName();
|
||||
|
||||
@Attribute("description")
|
||||
public abstract GenericAttributeValue<String> getDescription();
|
||||
|
||||
@Attribute("depends")
|
||||
@Convert(value = AntDomTargetDependsListConverter.class)
|
||||
public abstract GenericAttributeValue<TargetResolver.Result> getDependsList();
|
||||
|
||||
Reference in New Issue
Block a user