diff options
14 files changed, 792 insertions, 1 deletions
diff --git a/org.eclipse.jface.text/src/org/eclipse/jface/text/codemining/CodeMiningReconciler.java b/org.eclipse.jface.text/src/org/eclipse/jface/text/codemining/CodeMiningReconciler.java new file mode 100644 index 00000000000..74e0830eb98 --- /dev/null +++ b/org.eclipse.jface.text/src/org/eclipse/jface/text/codemining/CodeMiningReconciler.java @@ -0,0 +1,44 @@ +/**
+ * Copyright (c) 2017 Angelo ZERR.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Angelo Zerr <angelo.zerr@gmail.com> - [CodeMining] Provide extension point for CodeMining - Bug 528419
+ */
+package org.eclipse.jface.text.codemining;
+
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.ITextViewer;
+import org.eclipse.jface.text.reconciler.Reconciler;
+
+/**
+ * A reconciler which update code minings.
+ *
+ * @since 3.13
+ */
+public class CodeMiningReconciler extends Reconciler {
+
+ private CodeMiningStrategy fStrategy;
+
+ public CodeMiningReconciler() {
+ super.setIsIncrementalReconciler(false);
+ fStrategy= new CodeMiningStrategy();
+ this.setReconcilingStrategy(fStrategy, IDocument.DEFAULT_CONTENT_TYPE);
+ }
+
+ @Override
+ public void install(ITextViewer textViewer) {
+ super.install(textViewer);
+ fStrategy.install(textViewer);
+ }
+
+ @Override
+ public void uninstall() {
+ super.uninstall();
+ fStrategy.uninstall();
+ }
+
+}
diff --git a/org.eclipse.jface.text/src/org/eclipse/jface/text/codemining/CodeMiningStrategy.java b/org.eclipse.jface.text/src/org/eclipse/jface/text/codemining/CodeMiningStrategy.java new file mode 100644 index 00000000000..27e645801aa --- /dev/null +++ b/org.eclipse.jface.text/src/org/eclipse/jface/text/codemining/CodeMiningStrategy.java @@ -0,0 +1,74 @@ +/**
+ * Copyright (c) 2017 Angelo ZERR.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Angelo Zerr <angelo.zerr@gmail.com> - [CodeMining] Provide extension point for CodeMining - Bug 528419
+ */
+package org.eclipse.jface.text.codemining;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.ITextViewer;
+import org.eclipse.jface.text.reconciler.DirtyRegion;
+import org.eclipse.jface.text.reconciler.IReconcilingStrategy;
+import org.eclipse.jface.text.reconciler.IReconcilingStrategyExtension;
+import org.eclipse.jface.text.source.ISourceViewerExtension5;
+
+/**
+ * A reconciling strategy which updates code minings.
+ *
+ * @since 3.13
+ */
+class CodeMiningStrategy implements IReconcilingStrategy, IReconcilingStrategyExtension {
+
+ private ISourceViewerExtension5 fViewer;
+
+ public void install(ITextViewer viewer) {
+ if (viewer instanceof ISourceViewerExtension5) {
+ fViewer= (ISourceViewerExtension5) viewer;
+ }
+ }
+
+ @Override
+ public void initialReconcile() {
+ if (fViewer != null) {
+ // FIXME: this update is done because minings is not updated on focus by AbstractTextEditor#setFocus
+ // But I'm a little afraid to update minings each time editor will have focus
+ // @Mickael what do you think about doing update minings on AbstractTextEditor#setFocus ?
+ fViewer.updateCodeMinings();
+ }
+ }
+
+ @Override
+ public void reconcile(IRegion partition) {
+ if (fViewer != null) {
+ fViewer.updateCodeMinings();
+ }
+ }
+
+ public void uninstall() {
+ fViewer= null;
+ }
+
+ @Override
+ public void setProgressMonitor(IProgressMonitor monitor) {
+ // Do nothing
+ }
+
+ @Override
+ public void setDocument(IDocument document) {
+ // Do nothing
+ }
+
+ @Override
+ public void reconcile(DirtyRegion dirtyRegion, IRegion subRegion) {
+ // Do nothing
+ }
+
+}
diff --git a/org.eclipse.jface.text/src/org/eclipse/jface/text/source/SourceViewer.java b/org.eclipse.jface.text/src/org/eclipse/jface/text/source/SourceViewer.java index 0876ffd5783..824486d6920 100644 --- a/org.eclipse.jface.text/src/org/eclipse/jface/text/source/SourceViewer.java +++ b/org.eclipse.jface.text/src/org/eclipse/jface/text/source/SourceViewer.java @@ -769,6 +769,7 @@ public class SourceViewer extends TextViewer implements ISourceViewer, ISourceVi setCodeMiningProviders(null); if (fInlinedAnnotationSupport != null) { fInlinedAnnotationSupport.uninstall(); + fInlinedAnnotationSupport= null; } } diff --git a/org.eclipse.ui.genericeditor.examples/plugin.xml b/org.eclipse.ui.genericeditor.examples/plugin.xml index 0073c998635..48f28ce0bd6 100644 --- a/org.eclipse.ui.genericeditor.examples/plugin.xml +++ b/org.eclipse.ui.genericeditor.examples/plugin.xml @@ -95,4 +95,29 @@ targetId="org.eclipse.ui.genericeditor.GenericEditor"> </hyperlinkDetector> </extension> -</plugin> + <!-- ================== CodeMining support for .project ================== --> + <!-- 1) register CodeMining provider with extension point --> + <extension + point="org.eclipse.ui.workbench.texteditor.codeMiningProviders"> + <codeMiningProvider + class="org.eclipse.ui.genericeditor.examples.dotproject.codemining.ProjectReferencesCodeMiningProvider" + id="org.eclipse.ui.genericeditor.examples.dotproject.codemining.references" + label="Project references"> + <enabledWhen> + <with variable="editorInput"> + <adapt type="org.eclipse.core.resources.IFile"> + <test property="org.eclipse.core.resources.contentTypeId" value="org.eclipse.ui.genericeditor.examples.dotproject" /> + </adapt> + </with> + </enabledWhen> + </codeMiningProvider> + </extension> + <!-- 2) update CodeMining provider with a reconciler --> + <extension + point="org.eclipse.ui.genericeditor.reconcilers"> + <reconciler + class="org.eclipse.jface.text.codemining.CodeMiningReconciler" + contentType="org.eclipse.ui.genericeditor.examples.dotproject"> + </reconciler> + </extension> +</plugin>
\ No newline at end of file diff --git a/org.eclipse.ui.genericeditor.examples/src/org/eclipse/ui/genericeditor/examples/dotproject/codemining/ProjectReferenceCodeMining.java b/org.eclipse.ui.genericeditor.examples/src/org/eclipse/ui/genericeditor/examples/dotproject/codemining/ProjectReferenceCodeMining.java new file mode 100644 index 00000000000..e46bd352e5a --- /dev/null +++ b/org.eclipse.ui.genericeditor.examples/src/org/eclipse/ui/genericeditor/examples/dotproject/codemining/ProjectReferenceCodeMining.java @@ -0,0 +1,46 @@ +/**
+ * Copyright (c) 2017 Angelo ZERR.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Angelo Zerr <angelo.zerr@gmail.com> - [CodeMining] Provide extension point for CodeMining - Bug 528419
+ */
+package org.eclipse.ui.genericeditor.examples.dotproject.codemining;
+
+import java.util.concurrent.CompletableFuture;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.ITextViewer;
+import org.eclipse.jface.text.codemining.AbstractCodeMining;
+import org.eclipse.jface.text.codemining.ICodeMiningProvider;
+
+/**
+ * Project reference mining.
+ */
+public class ProjectReferenceCodeMining extends AbstractCodeMining {
+
+ private final String projectName;
+
+ public ProjectReferenceCodeMining(String projectName, int beforeLineNumber, IDocument document,
+ ICodeMiningProvider provider) throws BadLocationException {
+ super(beforeLineNumber, document, provider);
+ this.projectName = projectName;
+ }
+
+ @Override
+ protected CompletableFuture<Void> doResolve(ITextViewer viewer, IProgressMonitor monitor) {
+ return CompletableFuture.runAsync(() -> {
+ IProject project = ResourcesPlugin.getWorkspace().getRoot().getProject(projectName);
+ int refCount = project != null ? project.getReferencingProjects().length : 0;
+ super.setLabel(refCount + (refCount > 1 ? " references" : " reference"));
+ });
+ }
+
+}
diff --git a/org.eclipse.ui.genericeditor.examples/src/org/eclipse/ui/genericeditor/examples/dotproject/codemining/ProjectReferencesCodeMiningProvider.java b/org.eclipse.ui.genericeditor.examples/src/org/eclipse/ui/genericeditor/examples/dotproject/codemining/ProjectReferencesCodeMiningProvider.java new file mode 100644 index 00000000000..a1312fe23c0 --- /dev/null +++ b/org.eclipse.ui.genericeditor.examples/src/org/eclipse/ui/genericeditor/examples/dotproject/codemining/ProjectReferencesCodeMiningProvider.java @@ -0,0 +1,75 @@ +/**
+ * Copyright (c) 2017 Angelo ZERR.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Angelo Zerr <angelo.zerr@gmail.com> - [CodeMining] Provide extension point for CodeMining - Bug 528419
+ */
+package org.eclipse.ui.genericeditor.examples.dotproject.codemining;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.CompletableFuture;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.ITextViewer;
+import org.eclipse.jface.text.codemining.AbstractCodeMiningProvider;
+import org.eclipse.jface.text.codemining.ICodeMining;
+
+/**
+ * Project reference minings provider.
+ */
+public class ProjectReferencesCodeMiningProvider extends AbstractCodeMiningProvider {
+
+ @Override
+ public CompletableFuture<List<? extends ICodeMining>> provideCodeMinings(ITextViewer viewer,
+ IProgressMonitor monitor) {
+ return CompletableFuture.supplyAsync(() -> {
+ IDocument document = viewer.getDocument();
+ List<ICodeMining> minings = new ArrayList<>();
+ int lineCount = document.getNumberOfLines();
+ for (int i = 0; i < lineCount; i++) {
+ // check if request was canceled.
+ monitor.isCanceled();
+ String line = getLineText(document, i).trim();
+ int startIndex = line.indexOf("<name>");
+ if (startIndex != -1) {
+ // It's the first name, we consider we are in <projectDescription></name>
+ startIndex += "<name>".length();
+ int endIndex = line.indexOf("</name>");
+ if (endIndex > startIndex) {
+ // Check if parent element is projectDescription
+ String projectName = line.substring(startIndex, endIndex);
+ if (projectName.length() > 0) {
+ try {
+ minings.add(new ProjectReferenceCodeMining(projectName, i, document, this));
+ } catch (BadLocationException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ // stop the compute of minings to avoid process other name like
+ // <buildCommand><name>
+ break;
+ }
+ }
+ return minings;
+ });
+ }
+
+ private static String getLineText(IDocument document, int line) {
+ try {
+ int lo = document.getLineOffset(line);
+ int ll = document.getLineLength(line);
+ return document.get(lo, ll);
+ } catch (Exception e) {
+ e.printStackTrace();
+ return null;
+ }
+ }
+}
diff --git a/org.eclipse.ui.workbench.texteditor/META-INF/MANIFEST.MF b/org.eclipse.ui.workbench.texteditor/META-INF/MANIFEST.MF index c00bd616f34..4ab2c9ddb1d 100644 --- a/org.eclipse.ui.workbench.texteditor/META-INF/MANIFEST.MF +++ b/org.eclipse.ui.workbench.texteditor/META-INF/MANIFEST.MF @@ -10,6 +10,7 @@ Bundle-Localization: plugin Export-Package: org.eclipse.ui.contentassist, org.eclipse.ui.internal.texteditor; texteditor="split"; mandatory:="texteditor"; x-friends:="org.eclipse.ui.editors", + org.eclipse.ui.internal.texteditor.codemining;x-internal:=true, org.eclipse.ui.internal.texteditor.quickdiff;x-internal:=true, org.eclipse.ui.internal.texteditor.quickdiff.compare.equivalence;x-internal:=true, org.eclipse.ui.internal.texteditor.rulers;x-internal:=true, diff --git a/org.eclipse.ui.workbench.texteditor/plugin.properties b/org.eclipse.ui.workbench.texteditor/plugin.properties index d92f936fa82..a87812f3751 100644 --- a/org.eclipse.ui.workbench.texteditor/plugin.properties +++ b/org.eclipse.ui.workbench.texteditor/plugin.properties @@ -10,6 +10,7 @@ # Tom Eicher (Avaloq Evolution AG) - block selection mode # Daesung Ha <nberserk@gmail.com> - update recenter command description # Mickael Istria (Red Hat Inc.) - 469918 Zoom In/Out +# Angelo Zerr <angelo.zerr@gmail.com> - [CodeMining] Provide extension point for CodeMining - Bug 528419 ############################################################################### pluginName= Text Editor Framework providerName= Eclipse.org @@ -21,6 +22,7 @@ ExtPoint.referenceProvider= Reference Provider ExtPoint.rulerColumns= Ruler Columns ExtPoint.hyperlinkDetectors= Hyperlink Detectors ExtPoint.hyperlinkDetectorTargets= Hyperlink Detector Targets +ExtPoint.codeMiningProviders=CodeMining Providers textEditorPresentationActionSet.label= Editor Presentation diff --git a/org.eclipse.ui.workbench.texteditor/plugin.xml b/org.eclipse.ui.workbench.texteditor/plugin.xml index c5b9c212c8f..558c966b358 100644 --- a/org.eclipse.ui.workbench.texteditor/plugin.xml +++ b/org.eclipse.ui.workbench.texteditor/plugin.xml @@ -7,6 +7,7 @@ <extension-point id="rulerColumns" name="%ExtPoint.rulerColumns" schema="schema/rulerColumns.exsd"/> <extension-point id="hyperlinkDetectors" name="%ExtPoint.hyperlinkDetectors" schema="schema/hyperlinkDetectors.exsd"/> <extension-point id="hyperlinkDetectorTargets" name="%ExtPoint.hyperlinkDetectorTargets" schema="schema/hyperlinkDetectorTargets.exsd"/> + <extension-point id="codeMiningProviders" name="%ExtPoint.codeMiningProviders" schema="schema/codeMiningProviders.exsd"/> <extension point="org.eclipse.ui.commands"> diff --git a/org.eclipse.ui.workbench.texteditor/schema/codeMiningProviders.exsd b/org.eclipse.ui.workbench.texteditor/schema/codeMiningProviders.exsd new file mode 100644 index 00000000000..eaec16d7def --- /dev/null +++ b/org.eclipse.ui.workbench.texteditor/schema/codeMiningProviders.exsd @@ -0,0 +1,171 @@ +<?xml version='1.0' encoding='UTF-8'?> +<!-- Schema file written by PDE --> +<schema targetNamespace="org.eclipse.ui.workbench.texteditor" xmlns="http://www.w3.org/2001/XMLSchema"> +<annotation> + <appInfo> + <meta.schema plugin="org.eclipse.ui.workbench.texteditor" id="codeMiningProviders" name="CodeMining Providers"/> + </appInfo> + <documentation> + This extension point is used to register codemining providers. Associating providers via this extension doesn't automatically enable code-mining, and that clients are also supposed to use a reconcilier or whatever event mechanism to invoke ISourceViewerExtension5.updateCodeMinings(). + </documentation> + </annotation> + + <include schemaLocation="schema://org.eclipse.core.expressions/schema/expressionLanguage.exsd"/> + + <element name="extension"> + <annotation> + <appInfo> + <meta.element /> + </appInfo> + </annotation> + <complexType> + <sequence> + <element ref="codeMiningProvider" minOccurs="1" maxOccurs="unbounded"/> + </sequence> + <attribute name="point" type="string" use="required"> + <annotation> + <documentation> + a fully qualified identifier of the target extension point + </documentation> + </annotation> + </attribute> + <attribute name="id" type="string"> + <annotation> + <documentation> + an optional identifier of the extension instance + </documentation> + </annotation> + </attribute> + <attribute name="name" type="string"> + <annotation> + <documentation> + an optional name of the extension instance + </documentation> + <appInfo> + <meta.attribute translatable="true"/> + </appInfo> + </annotation> + </attribute> + </complexType> + </element> + + <element name="codeMiningProvider"> + <annotation> + <documentation> + A CodeMining provider. + </documentation> + </annotation> + <complexType> + <sequence> + <element ref="enabledWhen" minOccurs="0" maxOccurs="1"/> + </sequence> + <attribute name="id" type="string" use="required"> + <annotation> + <documentation> + a string uniquely identifying this codemining provider + </documentation> + </annotation> + </attribute> + <attribute name="class" type="string" use="required"> + <annotation> + <documentation> + the fully qualified class name implementing the interface <code>org.eclipse.jface.text.codemining.ICodeMiningProvider</code>. + </documentation> + <appInfo> + <meta.attribute kind="java" basedOn=":org.eclipse.jface.text.codemining.ICodeMiningProvider"/> + </appInfo> + </annotation> + </attribute> + <attribute name="label" type="string"> + <annotation> + <documentation> + the display label for the codemining provider, which will show in the CodeMining UI preferences + </documentation> + <appInfo> + <meta.attribute translatable="true"/> + </appInfo> + </annotation> + </attribute> + </complexType> + </element> + + <element name="enabledWhen"> + <annotation> + <documentation> + A core Expression that controls the enabled of the given codemining provider + </documentation> + </annotation> + <complexType> + <choice minOccurs="0" maxOccurs="1"> + <element ref="not"/> + <element ref="or"/> + <element ref="and"/> + <element ref="instanceof"/> + <element ref="test"/> + <element ref="systemTest"/> + <element ref="equals"/> + <element ref="count"/> + <element ref="with"/> + <element ref="resolve"/> + <element ref="adapt"/> + <element ref="iterate"/> + <element ref="reference"/> + </choice> + </complexType> + </element> + + <annotation> + <appInfo> + <meta.section type="since"/> + </appInfo> + <documentation> + 3.10 + </documentation> + </annotation> + + <annotation> + <appInfo> + <meta.section type="examples"/> + </appInfo> + <documentation> + The following is an example of a codemining provider definition: + +<pre> + <extension + point="org.eclipse.ui.workbench.texteditor.codeMiningProviders"> + <codeMiningProvider + class="org.eclipse.jdt.internal.ui.codemining.JavaReferencesCodeMiningProvider" + id="org.eclipse.jdt.ui.codemining.references" + label="Java References"> + <enabledWhen> + <with variable="editor"> + <instanceof value="org.eclipse.jdt.internal.ui.javaeditor.CompilationUnitEditor"/> + </with> + </enabledWhen> + </codeMiningProvider> + </extension> +</pre> + </documentation> + </annotation> + + <annotation> + <appInfo> + <meta.section type="apiInfo"/> + </appInfo> + <documentation> + See the org.eclipse.jface.text.codemining.ICodeMiningProvider class and the org.eclipse.ui.workbench.texteditor.codeMiningProviders extension point. + </documentation> + </annotation> + + + <annotation> + <appInfo> + <meta.section type="copyright"/> + </appInfo> + <documentation> + Copyright (c) 2017 Angelo ZERR.<br> +All rights reserved. This program and the accompanying materials are made available under the terms of the Eclipse Public License v1.0 which accompanies this distribution, and is available at <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a> + </documentation> + </annotation> + +</schema> diff --git a/org.eclipse.ui.workbench.texteditor/src/org/eclipse/ui/internal/texteditor/TextEditorPlugin.java b/org.eclipse.ui.workbench.texteditor/src/org/eclipse/ui/internal/texteditor/TextEditorPlugin.java index 019841b7aea..0f3bd80f4ca 100644 --- a/org.eclipse.ui.workbench.texteditor/src/org/eclipse/ui/internal/texteditor/TextEditorPlugin.java +++ b/org.eclipse.ui.workbench.texteditor/src/org/eclipse/ui/internal/texteditor/TextEditorPlugin.java @@ -7,6 +7,7 @@ * * Contributors: * IBM Corporation - initial API and implementation + * Angelo Zerr <angelo.zerr@gmail.com> - [CodeMining] Provide extension point for CodeMining - Bug 528419 *******************************************************************************/ package org.eclipse.ui.internal.texteditor; @@ -23,6 +24,7 @@ import org.eclipse.core.runtime.Platform; import org.eclipse.jface.action.IAction; +import org.eclipse.ui.internal.texteditor.codemining.CodeMiningProviderRegistry; import org.eclipse.ui.internal.texteditor.quickdiff.QuickDiffExtensionsRegistry; import org.eclipse.ui.internal.texteditor.spelling.SpellingEngineRegistry; import org.eclipse.ui.plugin.AbstractUIPlugin; @@ -63,6 +65,13 @@ public final class TextEditorPlugin extends AbstractUIPlugin implements IRegistr private SpellingEngineRegistry fSpellingEngineRegistry; /** + * The codemining provider registry + * + * @since 3.10 + */ + private CodeMiningProviderRegistry fCodeMiningProviderRegistry; + + /** * Creates a plug-in instance. */ public TextEditorPlugin() { @@ -150,6 +159,7 @@ public final class TextEditorPlugin extends AbstractUIPlugin implements IRegistr super.start(context); fQuickDiffExtensionRegistry= new QuickDiffExtensionsRegistry(); fSpellingEngineRegistry= new SpellingEngineRegistry(); + fCodeMiningProviderRegistry = new CodeMiningProviderRegistry(); Platform.getExtensionRegistry().addRegistryChangeListener(this, PLUGIN_ID); } @@ -158,6 +168,7 @@ public final class TextEditorPlugin extends AbstractUIPlugin implements IRegistr Platform.getExtensionRegistry().removeRegistryChangeListener(this); fQuickDiffExtensionRegistry= null; fSpellingEngineRegistry= null; + fCodeMiningProviderRegistry = null; super.stop(context); } @@ -167,6 +178,9 @@ public final class TextEditorPlugin extends AbstractUIPlugin implements IRegistr fQuickDiffExtensionRegistry.reloadExtensions(); if (fSpellingEngineRegistry != null && event.getExtensionDeltas(PLUGIN_ID, SpellingEngineRegistry.SPELLING_ENGINE_EXTENSION_POINT).length > 0) fSpellingEngineRegistry.reloadExtensions(); + if (fCodeMiningProviderRegistry != null && event.getExtensionDeltas(PLUGIN_ID, + CodeMiningProviderRegistry.CODEMINING_PROVIDERS_EXTENSION_POINT).length > 0) + fCodeMiningProviderRegistry.reloadExtensions(); } /** @@ -188,4 +202,15 @@ public final class TextEditorPlugin extends AbstractUIPlugin implements IRegistr public SpellingEngineRegistry getSpellingEngineRegistry() { return fSpellingEngineRegistry; } + + /** + * Returns this plug-ins codemining provider registry. + * + * @return the codemining provider registry or <code>null</code> if this plug-in + * has been shutdown + * @since 3.10 + */ + public CodeMiningProviderRegistry getCodeMiningProviderRegistry() { + return fCodeMiningProviderRegistry; + } } diff --git a/org.eclipse.ui.workbench.texteditor/src/org/eclipse/ui/internal/texteditor/codemining/CodeMiningProviderDescriptor.java b/org.eclipse.ui.workbench.texteditor/src/org/eclipse/ui/internal/texteditor/codemining/CodeMiningProviderDescriptor.java new file mode 100644 index 00000000000..8b758b02fec --- /dev/null +++ b/org.eclipse.ui.workbench.texteditor/src/org/eclipse/ui/internal/texteditor/codemining/CodeMiningProviderDescriptor.java @@ -0,0 +1,193 @@ +/** + * Copyright (c) 2017 Angelo ZERR. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr <angelo.zerr@gmail.com> - [CodeMining] Provide extension point for CodeMining - Bug 528419 + */ +package org.eclipse.ui.internal.texteditor.codemining; + +import org.eclipse.core.expressions.ElementHandler; +import org.eclipse.core.expressions.EvaluationContext; +import org.eclipse.core.expressions.EvaluationResult; +import org.eclipse.core.expressions.Expression; +import org.eclipse.core.expressions.ExpressionConverter; + +import org.eclipse.core.runtime.Assert; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IConfigurationElement; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; + +import org.eclipse.jface.text.codemining.AbstractCodeMiningProvider; +import org.eclipse.jface.text.codemining.ICodeMiningProvider; +import org.eclipse.jface.text.source.ISourceViewer; + +import org.eclipse.ui.internal.texteditor.TextEditorPlugin; + +import org.eclipse.ui.texteditor.ITextEditor; + +/** + * Describes an extension to the <code>codeMiningProviders</code> extension + * point. + * <p> + * This class is not intended to be subclassed by clients. + * </p> + * + * @since 3.10 + * @noextend This class is not intended to be subclassed by clients. + */ +class CodeMiningProviderDescriptor { + + /** Name of the <code>label</code> attribute. */ + private static final String LABEL_ATTRIBUTE = "label"; //$NON-NLS-1$ + /** Name of the <code>class</code> attribute. */ + private static final String CLASS_ATTRIBUTE = "class"; //$NON-NLS-1$ + /** Name of the <code>id</code> attribute. */ + private static final String ID_ATTRIBUTE = "id"; //$NON-NLS-1$ + /** Name of the <code>enabledWhen</code> attribute. **/ + private static final String ENABLED_WHEN_ATTR = "enabledWhen"; //$NON-NLS-1$ + + /** The configuration element describing this extension. */ + private IConfigurationElement fConfiguration; + /** The value of the <code>label</code> attribute, if read. */ + private String fLabel; + /** The value of the <code>id</code> attribute, if read. */ + private String fId; + /** The expression value of the <code>enabledWhen</code> attribute. */ + private final Expression fEnabledWhen; + + /** + * Creates a new descriptor for <code>element</code>. + * <p> + * This method is for internal use only. + * </p> + * + * @param element + * the extension point element to be described. + * @throws CoreException + * when <code>enabledWhen</code> expression is not valid. + */ + public CodeMiningProviderDescriptor(IConfigurationElement element) throws CoreException { + Assert.isLegal(element != null); + fConfiguration = element; + fEnabledWhen = createEnabledWhen(fConfiguration, getId()); + } + + /** + * Returns the expression {@link Expression} declared in the + * <code>enabledWhen</code> element. + * + * @param configElement + * the configuration element + * @param id + * the id of the codemining provider. + * @return the expression {@link Expression} declared in the enabledWhen + * element. + * @throws CoreException + * when enabledWhen expression is not valid. + */ + private static Expression createEnabledWhen(IConfigurationElement configElement, String id) throws CoreException { + final IConfigurationElement[] children = configElement.getChildren(ENABLED_WHEN_ATTR); + if (children.length > 0) { + IConfigurationElement[] subChildren = children[0].getChildren(); + if (subChildren.length != 1) { + throw new CoreException(new Status(IStatus.ERROR, TextEditorPlugin.PLUGIN_ID, + "One <enabledWhen> element is accepted. Disabling " + id)); //$NON-NLS-1$ + } + final ElementHandler elementHandler = ElementHandler.getDefault(); + final ExpressionConverter converter = ExpressionConverter.getDefault(); + return elementHandler.create(converter, subChildren[0]); + + } + throw new CoreException(new Status(IStatus.ERROR, TextEditorPlugin.PLUGIN_ID, + "<enabledWhen> element is required. Disabling " + id)); //$NON-NLS-1$ + } + + /** + * Reads (if needed) and returns the label of this extension. + * + * @return the label for this extension. + */ + public String getLabel() { + if (fLabel == null) { + fLabel = fConfiguration.getAttribute(LABEL_ATTRIBUTE); + Assert.isNotNull(fLabel); + } + return fLabel; + } + + /** + * Reads (if needed) and returns the id of this extension. + * + * @return the id for this extension. + */ + public String getId() { + if (fId == null) { + fId = fConfiguration.getAttribute(ID_ATTRIBUTE); + Assert.isNotNull(fId); + } + return fId; + } + + /** + * Creates a codemining provider as described in the extension's xml. and null + * otherwise. + * + * @param editor + * the text editor + * + * @return the created codemining provider and null otherwise. + */ + protected ICodeMiningProvider createCodeMiningProvider(ITextEditor editor) { + try { + Object extension = fConfiguration.createExecutableExtension(CLASS_ATTRIBUTE); + if (extension instanceof ICodeMiningProvider) { + if (extension instanceof AbstractCodeMiningProvider) { + ((AbstractCodeMiningProvider) extension).setContext(editor); + } + return (ICodeMiningProvider) extension; + } else { + String message = "Invalid extension to codeMiningProviders. Must extends ICodeMiningProvider: " //$NON-NLS-1$ + + getId(); + TextEditorPlugin.getDefault().getLog() + .log(new Status(IStatus.ERROR, TextEditorPlugin.PLUGIN_ID, message)); + return null; + } + } catch (CoreException e) { + TextEditorPlugin.getDefault().getLog().log(new Status(IStatus.ERROR, TextEditorPlugin.PLUGIN_ID, + "Error while creating codeMiningProvider: " + getId(), e)); //$NON-NLS-1$ + return null; + } + } + + /** + * Returns true if the given viewer, editor matches the enabledWhen expression + * and false otherwise. + * + * @param viewer + * the viewer + * @param editor + * the editor + * @return true if the given viewer, editor matches the enabledWhen expression + * and false otherwise. + */ + public boolean matches(ISourceViewer viewer, ITextEditor editor) { + EvaluationContext context = new EvaluationContext(null, editor); + context.setAllowPluginActivation(true); + context.addVariable("viewer", viewer); //$NON-NLS-1$ + context.addVariable("editor", editor); //$NON-NLS-1$ + context.addVariable("editorInput", editor.getEditorInput()); //$NON-NLS-1$ + try { + return fEnabledWhen.evaluate(context) == EvaluationResult.TRUE; + } catch (CoreException e) { + TextEditorPlugin.getDefault().getLog().log( + new Status(IStatus.ERROR, TextEditorPlugin.PLUGIN_ID, "Error while 'enabledWhen' evaluation", e)); //$NON-NLS-1$ + return false; + } + } + +} diff --git a/org.eclipse.ui.workbench.texteditor/src/org/eclipse/ui/internal/texteditor/codemining/CodeMiningProviderRegistry.java b/org.eclipse.ui.workbench.texteditor/src/org/eclipse/ui/internal/texteditor/codemining/CodeMiningProviderRegistry.java new file mode 100644 index 00000000000..f801bfb1431 --- /dev/null +++ b/org.eclipse.ui.workbench.texteditor/src/org/eclipse/ui/internal/texteditor/codemining/CodeMiningProviderRegistry.java @@ -0,0 +1,117 @@ +/** + * Copyright (c) 2017 Angelo ZERR. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr <angelo.zerr@gmail.com> - [CodeMining] Provide extension point for CodeMining - Bug 528419 + */ +package org.eclipse.ui.internal.texteditor.codemining; + +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IConfigurationElement; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Platform; +import org.eclipse.core.runtime.Status; + +import org.eclipse.jface.text.codemining.ICodeMiningProvider; +import org.eclipse.jface.text.source.ISourceViewer; + +import org.eclipse.ui.internal.texteditor.TextEditorPlugin; + +import org.eclipse.ui.texteditor.ITextEditor; + +/** + * A codemining providers registry used to access the + * {@link CodeMiningProviderDescriptor}s that describe the codemining provider + * extensions. + * + * @see CodeMiningProviderDescriptor + * @since 3.10 + */ +public class CodeMiningProviderRegistry { + + /** + * Extension id of spelling engine extension point. (value + * <code>"codeMiningProviders"</code>). + */ + public static final String CODEMINING_PROVIDERS_EXTENSION_POINT = "codeMiningProviders"; //$NON-NLS-1$ + + /** All descriptors */ + private CodeMiningProviderDescriptor[] fDescriptors; + + /** <code>true</code> iff the extensions have been loaded at least once */ + private boolean fLoaded = false; + + /** + * Returns all descriptors. + * + * @return all descriptors + */ + private CodeMiningProviderDescriptor[] getDescriptors() { + ensureExtensionsLoaded(); + return fDescriptors; + } + + /** + * Reads all extensions. + * <p> + * This method can be called more than once in order to reload from a changed + * extension registry. + * </p> + */ + public synchronized void reloadExtensions() { + List<CodeMiningProviderDescriptor> descriptors = new ArrayList<>(); + IConfigurationElement[] elements = Platform.getExtensionRegistry() + .getConfigurationElementsFor(TextEditorPlugin.PLUGIN_ID, CODEMINING_PROVIDERS_EXTENSION_POINT); + for (int i = 0; i < elements.length; i++) { + IConfigurationElement element = elements[i]; + try { + CodeMiningProviderDescriptor descriptor = new CodeMiningProviderDescriptor(element); + descriptors.add(descriptor); + } catch (CoreException e) { + TextEditorPlugin.getDefault().getLog() + .log(new Status(IStatus.ERROR, element.getNamespaceIdentifier(), e.getMessage())); + } + } + fDescriptors = descriptors.toArray(new CodeMiningProviderDescriptor[descriptors.size()]); + fLoaded = true; + } + + /** + * Ensures the extensions have been loaded at least once. + */ + private void ensureExtensionsLoaded() { + if (!fLoaded) + reloadExtensions(); + } + + /** + * Returns the codemining providers for the given viewer and editor and null + * otherwise. + * + * @param viewer + * the viewer + * @param editor + * the editor + * @return the codemining providers for the given viewer and editor and null + * otherwise. + */ + public ICodeMiningProvider[] getProviders(ISourceViewer viewer, ITextEditor editor) { + List<ICodeMiningProvider> providers = new ArrayList<>(); + for (CodeMiningProviderDescriptor descriptor : getDescriptors()) { + if (descriptor.matches(viewer, editor)) { + ICodeMiningProvider provider = descriptor.createCodeMiningProvider(editor); + if (provider != null) { + providers.add(provider); + } + } + } + return providers.size() > 0 ? providers.toArray(new ICodeMiningProvider[providers.size()]) : null; + } +} diff --git a/org.eclipse.ui.workbench.texteditor/src/org/eclipse/ui/texteditor/AbstractTextEditor.java b/org.eclipse.ui.workbench.texteditor/src/org/eclipse/ui/texteditor/AbstractTextEditor.java index c90f6e50e4c..0ad4a48a3d0 100644 --- a/org.eclipse.ui.workbench.texteditor/src/org/eclipse/ui/texteditor/AbstractTextEditor.java +++ b/org.eclipse.ui.workbench.texteditor/src/org/eclipse/ui/texteditor/AbstractTextEditor.java @@ -17,6 +17,7 @@ * Holger Voormann - Word Wrap - https://bugs.eclipse.org/bugs/show_bug.cgi?id=35779 * Florian Weßling <flo@cdhq.de> - Word Wrap - https://bugs.eclipse.org/bugs/show_bug.cgi?id=35779 * Andrey Loskutov <loskutov@gmx.de> - Word Wrap - https://bugs.eclipse.org/bugs/show_bug.cgi?id=35779 + * Angelo Zerr <angelo.zerr@gmail.com> - [CodeMining] Provide extension point for CodeMining - Bug 528419 *******************************************************************************/ package org.eclipse.ui.texteditor; @@ -150,6 +151,7 @@ import org.eclipse.jface.text.TabsToSpacesConverter; import org.eclipse.jface.text.TextEvent; import org.eclipse.jface.text.TextSelection; import org.eclipse.jface.text.TextUtilities; +import org.eclipse.jface.text.codemining.ICodeMiningProvider; import org.eclipse.jface.text.hyperlink.HyperlinkManager; import org.eclipse.jface.text.hyperlink.IHyperlinkDetector; import org.eclipse.jface.text.information.IInformationProvider; @@ -165,6 +167,7 @@ import org.eclipse.jface.text.source.IAnnotationModel; import org.eclipse.jface.text.source.ISourceViewer; import org.eclipse.jface.text.source.ISourceViewerExtension3; import org.eclipse.jface.text.source.ISourceViewerExtension4; +import org.eclipse.jface.text.source.ISourceViewerExtension5; import org.eclipse.jface.text.source.IVerticalRuler; import org.eclipse.jface.text.source.IVerticalRulerColumn; import org.eclipse.jface.text.source.IVerticalRulerExtension; @@ -4026,6 +4029,19 @@ public abstract class AbstractTextEditor extends EditorPart implements ITextEdit EnrichMode mode= store != null ? convertEnrichModePreference(store.getInt(PREFERENCE_HOVER_ENRICH_MODE)) : EnrichMode.AFTER_DELAY; ((ITextViewerExtension8)fSourceViewer).setHoverEnrichMode(mode); } + + if (fSourceViewer instanceof ISourceViewerExtension5) + installCodeMinigProviders(); + } + + /** + * Install codemining providers. + * @since 3.10 + */ + private void installCodeMinigProviders() { + ICodeMiningProvider[] providers = TextEditorPlugin.getDefault().getCodeMiningProviderRegistry() + .getProviders(this.getSourceViewer(), this); + ((ISourceViewerExtension5) fSourceViewer).setCodeMiningProviders(providers); } /** |