/* * 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 org.napile.idea.thermit.doc; 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; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.Nullable; import org.napile.idea.thermit.AntFilesProvider; import org.napile.idea.thermit.ThermitSupport; import org.napile.idea.thermit.config.impl.AntInstallation; import org.napile.idea.thermit.dom.AntDomElement; import org.napile.idea.thermit.dom.AntDomProject; import org.napile.idea.thermit.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.JarFileSystem; import com.intellij.openapi.vfs.LocalFileSystem; import com.intellij.openapi.vfs.VfsUtil; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.vfs.VirtualFileManager; 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; public class AntDomDocumentationProvider implements DocumentationProvider { private static final Logger LOG = Logger.getInstance("#org.napile.idea.thermit.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 = ThermitSupport.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 = ThermitSupport.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; } }