# HG changeset patch # Parent 790126fb43449fd7819f049eea68eb9afa3a10bf diff --git a/ant.grammar/nbproject/project.xml b/ant.grammar/nbproject/project.xml --- a/ant.grammar/nbproject/project.xml +++ b/ant.grammar/nbproject/project.xml @@ -100,7 +100,7 @@ 2 - 1.9.0 + 1.28.0 diff --git a/ant.grammar/src/org/netbeans/modules/ant/grammar/AntGrammar.java b/ant.grammar/src/org/netbeans/modules/ant/grammar/AntGrammar.java --- a/ant.grammar/src/org/netbeans/modules/ant/grammar/AntGrammar.java +++ b/ant.grammar/src/org/netbeans/modules/ant/grammar/AntGrammar.java @@ -45,6 +45,7 @@ package org.netbeans.modules.ant.grammar; import java.io.IOException; +import java.net.URI; import java.net.URL; import java.text.Collator; import java.util.ArrayList; @@ -66,6 +67,7 @@ import org.netbeans.modules.xml.api.model.GrammarResult; import org.netbeans.modules.xml.api.model.HintContext; import org.netbeans.modules.xml.spi.dom.AbstractNode; +import org.netbeans.modules.xml.api.model.DescriptionSource; import org.openide.filesystems.FileObject; import org.openide.filesystems.URLMapper; import org.openide.util.Enumerations; @@ -395,12 +397,17 @@ case PROJECT: case TARGET: list.add(new MyElement(element) { - @Override public String getDescription() { + private URL manpage; + + { ClassLoader cl = Lookup.getDefault().lookup(ClassLoader.class); - URL manpage = cl.getResource("org/apache/tools/ant/module/docs/ant-docs/Tasks/" + element + ".html"); + manpage = cl.getResource("org/apache/tools/ant/module/docs/ant-docs/Tasks/" + element + ".html"); if (manpage == null) { manpage = cl.getResource("org/apache/tools/ant/module/docs/ant-docs/Types/" + element + ".html"); } + } + + @Override public String getDescription() { if (manpage != null) { FileObject f = URLMapper.findFileObject(manpage); if (f != null) { @@ -413,6 +420,13 @@ } return null; } + + @Override + public URL getContentURL() { + return manpage; + } + + }); break; default: @@ -827,7 +841,7 @@ } - private static class MyElement extends AbstractResultNode implements Element { + private static class MyElement extends AbstractResultNode implements Element, DescriptionSource { private String name; @@ -850,7 +864,21 @@ public @Override String toString() { return name; } + + @Override + public DescriptionSource resolveLink(String link) { + return null; + } + + @Override + public boolean isExternal() { + return false; + } + @Override + public URL getContentURL() { + return null; + } } private static class MyAttr extends AbstractResultNode implements Attr { diff --git a/xml.core/nbproject/project.properties b/xml.core/nbproject/project.properties --- a/xml.core/nbproject/project.properties +++ b/xml.core/nbproject/project.properties @@ -42,7 +42,7 @@ javac.compilerargs=-Xlint -Xlint:-serial javac.source=1.6 -spec.version.base=1.27.0 +spec.version.base=1.28.0 is.autoload=true javadoc.packages=\ diff --git a/xml.core/src/org/netbeans/modules/xml/api/model/DescriptionSource.java b/xml.core/src/org/netbeans/modules/xml/api/model/DescriptionSource.java new file mode 100644 --- /dev/null +++ b/xml.core/src/org/netbeans/modules/xml/api/model/DescriptionSource.java @@ -0,0 +1,105 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2011 Oracle and/or its affiliates. All rights reserved. + * + * Oracle and Java are registered trademarks of Oracle and/or its affiliates. + * Other names may be trademarks of their respective owners. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common + * Development and Distribution License("CDDL") (collectively, the + * "License"). You may not use this file except in compliance with the + * License. You can obtain a copy of the License at + * http://www.netbeans.org/cddl-gplv2.html + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the + * specific language governing permissions and limitations under the + * License. When distributing the software, include this License Header + * Notice in each file and include the License file at + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the GPL Version 2 section of the License file that + * accompanied this code. If applicable, add the following below the + * License Header, with the fields enclosed by brackets [] replaced by + * your own identifying information: + * "Portions Copyrighted [year] [name of copyright owner]" + * + * If you wish your version of this file to be governed by only the CDDL + * or only the GPL Version 2, indicate your decision by adding + * "[Contributor] elects to include this software in this distribution + * under the [CDDL or GPL Version 2] license." If you do not indicate a + * single choice of license, a recipient has the option to distribute + * your version of this file under either the CDDL, the GPL Version 2 or + * to extend the choice of license to its licensees as provided above. + * However, if you add GPL Version 2 code and therefore, elected the GPL + * Version 2 license, then the option applies only if the new code is + * made subject to such option by the copyright holder. + * + * Contributor(s): + * + * Portions Copyrighted 2011 Sun Microsystems, Inc. + */ +package org.netbeans.modules.xml.api.model; + +import java.net.URI; +import java.net.URL; + +/** + * Optional mixin interface, which can be implemented together with the + * {@link GrammarResult} interface on the returned completion item. + * It allows to resolve links and provide description contents. + *

+ * Implementation may return null from {@link #getDescription} to + * indicate that the system should load contents from the URL supplied by {@link #getContentURL()}. + *

+ * The implementation may choose to provide the content URL to open within the IDE + * or in an external browser. Any links will be resolved relatively to that URL. + * For special cases, the implementation may resolve a link to another instance + * of DescriptionSource by implementing {@link #resolveLink(java.net.URI)}. + *

+ * If both {@link #getDescription} and {@link #getContentURL} return null, there's + * no description at all for the {@link GrammarResult}. + * + * @author sdedic + * @since 1.28 + */ +public interface DescriptionSource { + /** + * Provides text of the description. If the method returns null, the + * IDE will try to load contents of the {@link #getContentURL()} and use that + * as a description. + * + * @return Description contents or null, if contents should be loaded + * from {@link #getContentURL}. + */ + // @NullAllowed + public String getDescription(); + + /** + * True, if the description can be opened by an external browser, following the + * {@link #getContentURL}. + * + * @return true, if the content URL can be used outside of the IDE + */ + public boolean isExternal(); + + /** + * Returns URL for the content, so it can be retrieved. If this URL is provided, + * any link not resolved by {@link #resolveLink(java.net.URI)} will be treated + * as relative to this content URL. + * + * @return URL of the description content + */ + // @NullAllowed + public URL getContentURL(); + + /** + * Resolves a link in the documentation to another DescriptionSource. Can + * return null, if the link cannot be resolved. + * + * @param link link found in the text + * @return resolved description, or null + */ + // @NullAllowed + public DescriptionSource resolveLink(String link); +} diff --git a/xml.core/src/org/netbeans/modules/xml/api/model/GrammarResult.java b/xml.core/src/org/netbeans/modules/xml/api/model/GrammarResult.java --- a/xml.core/src/org/netbeans/modules/xml/api/model/GrammarResult.java +++ b/xml.core/src/org/netbeans/modules/xml/api/model/GrammarResult.java @@ -78,7 +78,11 @@ /** * @return provide additional information simplifing decision - * (suitable for tooltip) or null + * (suitable for tooltip) or null. If the description may contain + * links, consider to implement {@link DescriptionSource} on the same class, + * which allows to resolve those links to content and/or URLs. + * + * @since 1.28 - DescriptionSource extension */ String getDescription(); diff --git a/xml.text/manifest.mf b/xml.text/manifest.mf --- a/xml.text/manifest.mf +++ b/xml.text/manifest.mf @@ -1,6 +1,6 @@ Manifest-Version: 1.0 OpenIDE-Module: org.netbeans.modules.xml.text/2 +OpenIDE-Module-Implementation-Version: 1 OpenIDE-Module-Localizing-Bundle: org/netbeans/modules/xml/text/resources/Bundle.properties OpenIDE-Module-Layer: org/netbeans/modules/xml/text/resources/mf-layer.xml AutoUpdate-Show-In-Client: false -OpenIDE-Module-Specification-Version: 1.31 diff --git a/xml.text/nbproject/project.properties b/xml.text/nbproject/project.properties --- a/xml.text/nbproject/project.properties +++ b/xml.text/nbproject/project.properties @@ -42,6 +42,7 @@ javac.source=1.6 +spec.version.base=1.31 test.unit.cp.extra=${openide.dir}/core/openide.jar:${openide.loaders.dir}/core/openide-loaders.jar test.unit.run.cp.extra=${test.unit.cp.extra} disable.qa-functional.tests=true diff --git a/xml.text/nbproject/project.xml b/xml.text/nbproject/project.xml --- a/xml.text/nbproject/project.xml +++ b/xml.text/nbproject/project.xml @@ -166,12 +166,21 @@ + org.netbeans.modules.queries + + + + 1 + 1.25 + + + org.netbeans.modules.xml.core 2 - 1.14 + 1.28 diff --git a/xml.text/src/org/netbeans/modules/xml/text/completion/XMLResultItem.java b/xml.text/src/org/netbeans/modules/xml/text/completion/XMLResultItem.java --- a/xml.text/src/org/netbeans/modules/xml/text/completion/XMLResultItem.java +++ b/xml.text/src/org/netbeans/modules/xml/text/completion/XMLResultItem.java @@ -49,7 +49,11 @@ import java.awt.Font; import java.awt.Graphics; import java.awt.event.KeyEvent; +import java.io.IOException; +import java.net.MalformedURLException; import java.net.URL; +import java.util.logging.Level; +import java.util.logging.Logger; import javax.swing.Action; import javax.swing.text.*; import javax.swing.Icon; @@ -57,13 +61,18 @@ import org.netbeans.editor.*; import javax.swing.JLabel; import org.netbeans.api.editor.completion.Completion; +import org.netbeans.api.queries.FileEncodingQuery; import org.netbeans.modules.xml.api.model.GrammarResult; +import org.netbeans.modules.xml.api.model.DescriptionSource; import org.netbeans.modules.xml.text.api.XMLDefaultTokenContext; import org.netbeans.modules.xml.text.syntax.XMLSyntaxSupport; import org.netbeans.spi.editor.completion.CompletionDocumentation; import org.netbeans.spi.editor.completion.CompletionItem; import org.netbeans.spi.editor.completion.CompletionResultSet; import org.netbeans.spi.editor.completion.CompletionTask; +import org.openide.filesystems.FileObject; +import org.openide.filesystems.URLMapper; +import org.openide.util.Exceptions; /** * This class carries result information required by NetBeans Editor module. @@ -72,6 +81,7 @@ * @author Sandeep Randhawa */ class XMLResultItem implements CompletionItem { + private static final Logger LOG = Logger.getLogger(XMLResultItem.class.getName()); // text to be diplayed to user public final String displayText; @@ -304,25 +314,148 @@ protected CompletionTask doCreateDocumentationTask(final GrammarResult res) { return new CompletionTask() { public void query(CompletionResultSet resultSet) { - if (res != null && res.getDescription() != null) { - resultSet.setDocumentation(new Docum(res.getDescription())); - + CompletionDocumentation cd = create(); + if (cd != null) { + resultSet.setDocumentation(cd); } resultSet.finish(); } public void refresh(CompletionResultSet resultSet) { - if (res != null && res.getDescription() != null) { - resultSet.setDocumentation(new Docum(res.getDescription())); - } - resultSet.finish(); + query(resultSet); } public void cancel() {} + + + private CompletionDocumentation create() { + String doc; + + doc = res.getDescription(); + if (!(res instanceof DescriptionSource)) { + if (doc == null) { + return null; + } + return new Docum(doc); + } else { + DescriptionSource ds = (DescriptionSource)res; + if (doc == null && ds.getContentURL() == null) { + return null; + } + return new ExtDocum(ds, doc); + } + } }; } + + /** + * Extended documentation, based on the {@link DescriptionSource} SPI. + */ + private static class ExtDocum extends URLDocum implements CompletionDocumentation { + private DescriptionSource src; + private String doc; + + ExtDocum(DescriptionSource src, String doc) { + super(src.getContentURL(), src.isExternal()); + this.src = src; + this.doc = doc; + } + + @Override + public String getText() { + if (doc == null) { + doc = src.getDescription(); + if (doc == null) { + doc = super.getText(); + } + } + return doc; + } + + @Override + public CompletionDocumentation resolveLink(String link) { + try { + DescriptionSource target = src.resolveLink(link); + if (target != null) { + return new ExtDocum(target, null); + } + + URL base = src.getContentURL(); + if (base == null) { + // sorry, cannot resolve. + return null; + } + + URL targetURL = new URL(base, link); + return new URLDocum(targetURL, src.isExternal()); + } catch (MalformedURLException ex) { + Exceptions.printStackTrace(ex); + return null; + } + } + + @Override + public Action getGotoSourceAction() { + return null; + } + } + + /** + * Pure URL documentation item. Resolves links, if original URL was able + * to open externally, the derived URLs do it as well. + */ + private static class URLDocum implements CompletionDocumentation { + URL content; + boolean external; + + URLDocum(URL content, boolean external) { + this.content = content; + this.external = external; + } + + URLDocum(boolean external) { + this.external = external; + } + + @Override + public Action getGotoSourceAction() { + return null; + } + + @Override + public String getText() { + FileObject f = URLMapper.findFileObject(content); + if (f != null) { + try { + return new String(f.asBytes(), FileEncodingQuery.getEncoding(f)); + } catch (IOException x) { + LOG.log(Level.INFO, "Could not load " + content, x); + } + } + return null; + } + + @Override + public URL getURL() { + return external ? content : null; + } + + @Override + public CompletionDocumentation resolveLink(String link) { + if (content == null) { + return null; + } + try { + return new URLDocum(new URL(content, link), external); + } catch (MalformedURLException ex) { + Exceptions.printStackTrace(ex); + return null; + } + } + + } private static class Docum implements CompletionDocumentation { private String doc; - + private Docum(String doc) { this.doc = doc; }