From 475c93f89d78e03eb0a65ab0e1f89120dbaedfa0 Mon Sep 17 00:00:00 2001 From: Oleg Krasilnikov Date: Wed, 24 Oct 2007 09:30:40 +0000 Subject: [PATCH] Bug #205030 : CHelpProvider for providing F1/hover docs info via XML should be implemented --- core/org.eclipse.cdt.ui/plugin.properties | 2 + core/org.eclipse.cdt.ui/plugin.xml | 11 +- core/org.eclipse.cdt.ui/schema/HelpInfo.exsd | 127 ++++++++++++++ .../internal/ui/help/CFunctionSummary.java | 110 ++++++++++++ .../cdt/internal/ui/help/CHelpBook.java | 144 +++++++++++++++ .../cdt/internal/ui/help/CHelpEntry.java | 62 +++++++ .../cdt/internal/ui/help/CHelpProvider.java | 166 ++++++++++++++++++ .../cdt/internal/ui/help/CHelpTopic.java | 28 +++ .../eclipse/cdt/internal/ui/util/CUIHelp.java | 3 +- 9 files changed, 651 insertions(+), 2 deletions(-) create mode 100644 core/org.eclipse.cdt.ui/schema/HelpInfo.exsd create mode 100644 core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/help/CFunctionSummary.java create mode 100644 core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/help/CHelpBook.java create mode 100644 core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/help/CHelpEntry.java create mode 100644 core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/help/CHelpProvider.java create mode 100644 core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/help/CHelpTopic.java diff --git a/core/org.eclipse.cdt.ui/plugin.properties b/core/org.eclipse.cdt.ui/plugin.properties index 2da7e660e01..01a21855c21 100644 --- a/core/org.eclipse.cdt.ui/plugin.properties +++ b/core/org.eclipse.cdt.ui/plugin.properties @@ -427,3 +427,5 @@ Cproject.desc=Create a new C project TemplatePreferencePage.name=Template Default Values Template.Engine.Wizard=template entries contributor ConfigManager=Dialog for Configurations management + +HelpInfo=Allows contributing the map files to the map-file-based CDT CHelpProvider. \ No newline at end of file diff --git a/core/org.eclipse.cdt.ui/plugin.xml b/core/org.eclipse.cdt.ui/plugin.xml index 46b65d15af3..519cf5dc363 100644 --- a/core/org.eclipse.cdt.ui/plugin.xml +++ b/core/org.eclipse.cdt.ui/plugin.xml @@ -22,6 +22,7 @@ + @@ -2257,4 +2258,12 @@ markerType="org.eclipse.cdt.core.problem"> - + + + + + + diff --git a/core/org.eclipse.cdt.ui/schema/HelpInfo.exsd b/core/org.eclipse.cdt.ui/schema/HelpInfo.exsd new file mode 100644 index 00000000000..65d08b37ffa --- /dev/null +++ b/core/org.eclipse.cdt.ui/schema/HelpInfo.exsd @@ -0,0 +1,127 @@ + + + + + + + + + Allows contributing the map files to +the map-file-based CDT CHelpProvider. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Allows defining map-file path relative to the plugin directory. + + + + + + + Contains map-file path relative to the plugin directory. + + + + + + + + + + May contain ID of map file format. +For now, there's only one (default) help map format. + + + + + + + + + + + + + CDT 4.0.2 + + + + + + + + + <extension + point="org.eclipse.cdt.ui.HelpInfo" + id="org.eclipse.cdt.ui.help.cpp" + name="C++ Help"> + <helpInfo file="data1.xml"/> + <helpInfo file="data2.xml"/> + <helpInfo file="data3.xml"/> +</extension> + + + + + + + + + [Enter API information here.] + + + + + + + + + [Enter information about supplied implementation of this extension point.] + + + + + + + + + + + + + diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/help/CFunctionSummary.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/help/CFunctionSummary.java new file mode 100644 index 00000000000..0ef08cea3f0 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/help/CFunctionSummary.java @@ -0,0 +1,110 @@ +package org.eclipse.cdt.internal.ui.help; + +import java.util.ArrayList; + +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +import org.eclipse.cdt.ui.FunctionPrototypeSummary; +import org.eclipse.cdt.ui.IFunctionSummary; +import org.eclipse.cdt.ui.IRequiredInclude; + +public class CFunctionSummary implements IFunctionSummary { + private static final String ATTR_STD = "standard"; //$NON-NLS-1$ + private static final String NODE_NAME = "name"; //$NON-NLS-1$ + private static final String NODE_DESC = "description"; //$NON-NLS-1$ + private static final String NODE_INCL = "include"; //$NON-NLS-1$ + private static final String NODE_TYPE = "returnType"; //$NON-NLS-1$ + private static final String NODE_ARGS = "arguments"; //$NON-NLS-1$ + + private static final String SP = " "; //$NON-NLS-1$ + private static final String LB = "("; //$NON-NLS-1$ + private static final String RB = ")"; //$NON-NLS-1$ + + private String name = null; + private String desc = null; + private IRequiredInclude[] incs = null; + IFunctionPrototypeSummary fps = null; + + public CFunctionSummary(Element e, String defName) { + name = defName; // if there's no "name" tag, keyword used instead + String args = null; + String type = null; + NodeList list = e.getChildNodes(); + ArrayList incList = new ArrayList(); + for(int j = 0; j < list.getLength(); j++){ + Node node = list.item(j); + if(node.getNodeType() != Node.ELEMENT_NODE) + continue; + String s = node.getNodeName().trim(); + String t = node.getFirstChild().getNodeValue().trim(); + if(NODE_NAME.equals(s)){ + name = t; + } else if(NODE_DESC.equals(s)){ + desc = t; + } else if(NODE_ARGS.equals(s)){ + args = t; + } else if(NODE_TYPE.equals(s)){ + type = t; + } else if(NODE_INCL.equals(s)){ + boolean std = true; + if (((Element)node).hasAttribute(ATTR_STD)) { + String st = ((Element)node).getAttribute(ATTR_STD); + std = (st == null || st.equalsIgnoreCase("true") //$NON-NLS-1$ + || st.equalsIgnoreCase("yes")); //$NON-NLS-1$ + } + incList.add(new RequiredInclude(t, std)); + } + } + if (incList.size() > 0) + incs = (IRequiredInclude[])incList.toArray( + new IRequiredInclude[incList.size()]); + fps = new FunctionPrototypeSummary(type + SP + name + LB + args + RB); + } + + public String getDescription() { + return desc; + } + public IRequiredInclude[] getIncludes() { + return incs; + } + public String getName() { + return name; + } + public String getNamespace() { + return null; + } + public IFunctionPrototypeSummary getPrototype() { + return fps; + } + + /** + * This class implements IRequiredInclude interface + */ + private class RequiredInclude implements IRequiredInclude { + private String iname; + private boolean std; + + private RequiredInclude(String s, boolean b) { + iname = s; + std = b; + } + public String getIncludeName() { + return iname; + } + public boolean isStandard() { + return std; + } + public String toString() { + if (std) + return "#include <" + iname + ">"; //$NON-NLS-1$ //$NON-NLS-2$ + else + return "#include \"" + iname + "\""; //$NON-NLS-1$ //$NON-NLS-2$ + } + } + public String toString() { + return " : " + getPrototype().getPrototypeString(false); //$NON-NLS-1$ + } + +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/help/CHelpBook.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/help/CHelpBook.java new file mode 100644 index 00000000000..15db59f3289 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/help/CHelpBook.java @@ -0,0 +1,144 @@ +package org.eclipse.cdt.internal.ui.help; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.SortedMap; +import java.util.TreeMap; + +import org.eclipse.help.IHelpResource; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +import org.eclipse.cdt.ui.ICHelpBook; +import org.eclipse.cdt.ui.ICHelpResourceDescriptor; +import org.eclipse.cdt.ui.IFunctionSummary; +import org.eclipse.cdt.ui.text.ICHelpInvocationContext; + +public class CHelpBook implements ICHelpBook { + private static final String ATTR_TITLE = "title"; //$NON-NLS-1$ + private static final String ATTR_BTYPE = "type"; //$NON-NLS-1$ + private static final String NODE_ENTRY = "entry"; //$NON-NLS-1$ + + private int type; + private String title; + private TreeMap entries; + + public CHelpBook(Element e) { + entries = new TreeMap(); + + if (e.hasAttribute(ATTR_TITLE)) + title = e.getAttribute(ATTR_TITLE).trim(); + if (e.hasAttribute(ATTR_BTYPE)) { + try { + type = Integer.parseInt(e.getAttribute(ATTR_TITLE)); + } catch (NumberFormatException ee) {} + } + NodeList list = e.getChildNodes(); + for(int i = 0; i < list.getLength(); i++){ + Node node = list.item(i); + if(node.getNodeType() != Node.ELEMENT_NODE) continue; + if(NODE_ENTRY.equals(node.getNodeName())) { + CHelpEntry he = new CHelpEntry((Element)node); + if (he.isValid()) + add(he.getKeyword(), he); + } + } + } + + public int getCHelpType() { + return type; + } + + public String getTitle() { + return title; + } + + private void add(String keyword, Object entry) { + entries.put(keyword, entry); + } + + public IFunctionSummary getFunctionInfo( + ICHelpInvocationContext context, + String name) { + + if (entries.containsKey(name)) { + CHelpEntry he = (CHelpEntry)entries.get(name); + IFunctionSummary[] fs = he.getFunctionSummary(); + if (fs != null && fs.length > 0) + return fs[0]; + // TODO: function summary selection + } + return null; + } + + /** + * Temporary implementation with slow search + * @param context + * @param prefix + * @return matching functions + */ + public List getMatchingFunctions( + ICHelpInvocationContext context, + String prefix) { + + Collection col = null; + if (prefix == null || prefix.trim().length() == 0) { + // return whole data + col = entries.values(); + } else { + String pr1 = prefix.trim(); + byte[] bs = pr1.getBytes(); + int i = bs.length - 1; + while (i >= 0) { + byte b = bs[i]; + if (++b > bs[i]) { // no overflow + bs[i] = b; + break; + } else + i--; + } + SortedMap sm = (i>-1) ? + entries.subMap(pr1, new String(bs)) : + entries.tailMap(pr1); + col = sm.values(); + } + + if (col.size() > 0) + return new ArrayList(col); + else + return null; + } + + public ICHelpResourceDescriptor getHelpResources( + ICHelpInvocationContext context, String name) { + if (entries.containsKey(name)) { + CHelpEntry he = (CHelpEntry)entries.get(name); + IHelpResource[] hr = he.getHelpResource(); + if (hr != null && hr.length > 0) + return new HRDescriptor(this, hr); + } + return null; + } + + private class HRDescriptor implements ICHelpResourceDescriptor { + private ICHelpBook book; + private IHelpResource[] res; + HRDescriptor(ICHelpBook _book, IHelpResource[] _res) { + book = _book; + res = _res; + } + public ICHelpBook getCHelpBook() { + return book; + } + public IHelpResource[] getHelpResources() { + return res; + } + } + + public String toString() { + return ""; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + } + +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/help/CHelpEntry.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/help/CHelpEntry.java new file mode 100644 index 00000000000..5bb8e08a6f2 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/help/CHelpEntry.java @@ -0,0 +1,62 @@ +package org.eclipse.cdt.internal.ui.help; + +import java.util.ArrayList; + +import org.eclipse.help.IHelpResource; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +import org.eclipse.cdt.ui.IFunctionSummary; + +public class CHelpEntry { + private static final String ATTR_KEYWD = "keyword"; //$NON-NLS-1$ + private static final String NODE_TOPIC = "topic"; //$NON-NLS-1$ + private static final String NODE_FSUMM = "functionSummary"; //$NON-NLS-1$ + + private String keyword = null; + private boolean isValid = true; + private CHelpTopic[] hts = null; + private CFunctionSummary[] fss = null; + + public CHelpEntry(Element e) { + keyword = e.getAttribute(ATTR_KEYWD).trim(); + ArrayList obs1 = new ArrayList(); + ArrayList obs2 = new ArrayList(); + NodeList list = e.getChildNodes(); + for(int i = 0; i < list.getLength(); i++){ + Node node = list.item(i); + if (node.getNodeType() != Node.ELEMENT_NODE) + continue; + if (NODE_FSUMM.equals(node.getNodeName())){ + obs1.add(new CFunctionSummary((Element)node, keyword)); + } else if (NODE_TOPIC.equals(node.getNodeName())) { + obs2.add(new CHelpTopic((Element)node, keyword)); + } + } + fss = (CFunctionSummary[])obs1.toArray(new CFunctionSummary[obs1.size()]); + hts = (CHelpTopic[])obs2.toArray(new CHelpTopic[obs2.size()]); + } + + /** + * Returns true if help entry is correct + * Returns false if entry is empty or when + * subsequent processing failed somehow. + * @return entry state + */ + public boolean isValid() { + return isValid; + } + public String getKeyword() { + return keyword; + } + public IFunctionSummary[] getFunctionSummary() { + return fss; + } + public IHelpResource[] getHelpResource() { + return hts; + } + public String toString() { + return ""; //$NON-NLS-1$ //$NON-NLS-2$ + } +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/help/CHelpProvider.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/help/CHelpProvider.java new file mode 100644 index 00000000000..7971c51aba7 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/help/CHelpProvider.java @@ -0,0 +1,166 @@ +package org.eclipse.cdt.internal.ui.help; + +import java.io.BufferedReader; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.net.URL; +import java.util.ArrayList; +import java.util.List; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; + +import org.eclipse.core.runtime.FileLocator; +import org.eclipse.core.runtime.IConfigurationElement; +import org.eclipse.core.runtime.IExtension; +import org.eclipse.core.runtime.IExtensionPoint; +import org.eclipse.core.runtime.Path; +import org.eclipse.core.runtime.Platform; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; + +import org.eclipse.cdt.ui.ICHelpBook; +import org.eclipse.cdt.ui.ICHelpProvider; +import org.eclipse.cdt.ui.ICHelpResourceDescriptor; +import org.eclipse.cdt.ui.IFunctionSummary; +import org.eclipse.cdt.ui.text.ICHelpInvocationContext; + +public class CHelpProvider implements ICHelpProvider { + + private static final String EXTENSION_POINT_ID = "org.eclipse.cdt.ui.HelpInfo"; //$NON-NLS-1$ + private static final String ELEMENT_NAME = "helpInfo"; //$NON-NLS-1$ + private static final String ATTRIB_FILE = "file"; //$NON-NLS-1$ + private static final String NODE_HEAD = "documentation"; //$NON-NLS-1$ + private static final String NODE_BOOK = "helpBook"; //$NON-NLS-1$ + + ICHelpBook[] hbs = null; + + public ICHelpBook[] getCHelpBooks() { + return hbs; + } + + public IFunctionSummary getFunctionInfo( + ICHelpInvocationContext context, + ICHelpBook[] helpBooks, + String name) { + for (int i=0; i 0) + return (ICHelpResourceDescriptor[])lst.toArray( + new ICHelpResourceDescriptor[lst.size()]); + else + return null; + } + + public IFunctionSummary[] getMatchingFunctions( + ICHelpInvocationContext context, ICHelpBook[] helpBooks, + String prefix) { + ArrayList lst = new ArrayList(); + for (int i=0; i 0) + return (IFunctionSummary[])lst.toArray(new IFunctionSummary[lst.size()]); + else + return null; + } + + public void initialize() { + loadExtensions(); + System.out.println(); + } + + private void loadExtensions() + { + IExtensionPoint extensionPoint = Platform.getExtensionRegistry() + .getExtensionPoint(EXTENSION_POINT_ID); + if (extensionPoint == null) return; + IExtension[] extensions = extensionPoint.getExtensions(); + if (extensions == null) return; + + ArrayList chbl = new ArrayList(); + + for (int i = 0; i < extensions.length; ++i) { + String pluginId = extensions[i].getNamespaceIdentifier(); + IConfigurationElement[] elements = extensions[i].getConfigurationElements(); + for (int k = 0; k < elements.length; k++) { + if (elements[k].getName().equals(ELEMENT_NAME)) { + loadFile(elements[k], chbl, pluginId); + } + } + } + if (chbl.size() > 0) { + hbs = (ICHelpBook[])chbl.toArray(new ICHelpBook[chbl.size()]); + } + } + + private void loadFile(IConfigurationElement el, ArrayList chbl, String pluginId) { + String fname = el.getAttribute(ATTRIB_FILE); + if (fname == null || fname.trim().length() == 0) return; + URL x = FileLocator.find(Platform.getBundle(pluginId), new Path(fname), null); + if (x == null) return; + try { x = FileLocator.toFileURL(x); + } catch (IOException e) { return; } + fname = x.getPath(); + if (fname == null || fname.trim().length() == 0) return; + + // format is not supported for now + // String format = el.getAttribute(ATTRIB_FORMAT); + + Document doc = null; + try { + InputStream stream = new FileInputStream(fname); + BufferedReader reader = new BufferedReader(new InputStreamReader(stream)); + InputSource src = new InputSource(reader); + DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder(); + doc = builder.parse(src); + } catch (ParserConfigurationException e) { + } catch (SAXException e) { + } catch (IOException e) { + } + + Element e = doc.getDocumentElement(); + if(NODE_HEAD.equals(e.getNodeName())){ + NodeList list = e.getChildNodes(); + for(int j = 0; j < list.getLength(); j++){ + Node node = list.item(j); + if(node.getNodeType() != Node.ELEMENT_NODE) continue; + if(NODE_BOOK.equals(node.getNodeName())){ + chbl.add(new CHelpBook((Element)node)); + } + } + } + } + +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/help/CHelpTopic.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/help/CHelpTopic.java new file mode 100644 index 00000000000..30e5da73a93 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/help/CHelpTopic.java @@ -0,0 +1,28 @@ +package org.eclipse.cdt.internal.ui.help; + +import org.eclipse.help.IHelpResource; +import org.w3c.dom.Element; + +public class CHelpTopic implements IHelpResource { + private static final String ATTR_TITLE = "title"; //$NON-NLS-1$ + private static final String ATTR_HREF = "href"; //$NON-NLS-1$ + + private String href = null; + private String title = null; + + public CHelpTopic(Element e, String defTitle) { + href = e.getAttribute(ATTR_HREF).trim(); + title = e.getAttribute(ATTR_TITLE).trim(); + if (title == null || title.length() == 0) + title = defTitle; + } + public String getHref() { + return href; + } + public String getLabel() { + return title; + } + public String toString() { + return ""; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + } +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/util/CUIHelp.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/util/CUIHelp.java index 472cd0550a5..980498797e5 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/util/CUIHelp.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/util/CUIHelp.java @@ -117,7 +117,8 @@ public class CUIHelp { ITextSelection selection = (ITextSelection)editor.getSite().getSelectionProvider().getSelection(); IDocument document = editor.getDocumentProvider().getDocument(editor.getEditorInput()); IRegion region = CWordFinder.findWord(document, selection.getOffset()); - expression = document.get(region.getOffset(), region.getLength()); + if (region != null) + expression = document.get(region.getOffset(), region.getLength()); } catch(Exception e){ }