| /* |
| * 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.AntFilesProvider; |
| 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.documentation.DocumentationProvider; |
| import com.intellij.openapi.diagnostic.Logger; |
| 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 { |
| |
| private static final Logger LOG = Logger.getInstance("#com.intellij.lang.ant.doc.AntDomDocumentationProvider"); |
| |
| 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); |
| } |
| |
| public static final String[] DOC_FOLDER_NAMES = new String[] { |
| "Tasks", "Types", "CoreTasks", "OptionalTasks", "CoreTypes", "OptionalTypes" |
| }; |
| |
| @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"; |
| |
| for (String folderName : DOC_FOLDER_NAMES) { |
| final VirtualFile candidateHelpFile = documentationRoot.findFileByRelativePath(folderName + helpFileShortName); |
| if (candidateHelpFile != null) { |
| return candidateHelpFile; |
| } |
| } |
| |
| if(antElement instanceof AntDomTarget|| antElement instanceof AntDomProject) { |
| final VirtualFile candidateHelpFile = documentationRoot.findFileByRelativePath("using.html"); |
| if (candidateHelpFile != null) { |
| return candidateHelpFile; |
| } |
| } |
| |
| return null; |
| } |
| |
| @Nullable |
| public String getQuickNavigateInfo(PsiElement element, PsiElement originalElement) { // 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; |
| Type type = null; |
| try { |
| type = description.getType(); |
| } |
| catch (UnsupportedOperationException e) { |
| LOG.info(e); |
| } |
| 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; |
| } |
| } |