Skip to main content
aboutsummaryrefslogtreecommitdiffstats
blob: ec9b31d9d777e951cb6e363993e7881f34487f2a (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
/**
 *  Copyright (c) 2017 Angelo ZERR.
 *
 *  This program and the accompanying materials
 *  are made available under the terms of the Eclipse Public License 2.0
 *  which accompanies this distribution, and is available at
 *  https://www.eclipse.org/legal/epl-2.0/
 *
 *  SPDX-License-Identifier: EPL-2.0
 *
 *  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]);
		}
		return null;
	}

	/**
	 * 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) {
		if (fEnabledWhen == null) {
			return true;
		}
		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;
		}
	}

}

Back to the top