| /******************************************************************************* |
| * Copyright (c) 2006, 2021 IBM Corporation and others. |
| * |
| * 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: |
| * IBM Corporation - initial API and implementation |
| * Brock Janiczak (brockj@tpg.com.au) - bug 197410 |
| * Benjamin Cabe (benjamin.cabe@anyware-tech.com) - bug 253692 |
| * Alex Blewitt (alex.blewitt@gmail.com) - bug 469803 |
| *******************************************************************************/ |
| package org.eclipse.pde.internal.ui.editor.contentassist; |
| |
| import java.util.*; |
| import org.eclipse.core.resources.IProject; |
| import org.eclipse.jdt.core.*; |
| import org.eclipse.jdt.core.search.IJavaSearchConstants; |
| import org.eclipse.jdt.launching.JavaRuntime; |
| import org.eclipse.jdt.launching.environments.IExecutionEnvironment; |
| import org.eclipse.jface.resource.ImageDescriptor; |
| import org.eclipse.jface.text.*; |
| import org.eclipse.jface.text.IRegion; |
| import org.eclipse.jface.text.contentassist.*; |
| import org.eclipse.osgi.service.resolver.BundleDescription; |
| import org.eclipse.osgi.service.resolver.ExportPackageDescription; |
| import org.eclipse.osgi.util.ManifestElement; |
| import org.eclipse.pde.core.plugin.*; |
| import org.eclipse.pde.internal.core.ICoreConstants; |
| import org.eclipse.pde.internal.core.util.HeaderMap; |
| import org.eclipse.pde.internal.core.util.PDEJavaHelper; |
| import org.eclipse.pde.internal.ui.PDEPluginImages; |
| import org.eclipse.pde.internal.ui.editor.PDEFormEditor; |
| import org.eclipse.pde.internal.ui.editor.PDESourcePage; |
| import org.eclipse.pde.internal.ui.editor.plugin.ManifestEditor; |
| import org.eclipse.pde.internal.ui.util.ImageOverlayIcon; |
| import org.eclipse.pde.internal.ui.util.PDEJavaHelperUI; |
| import org.eclipse.swt.graphics.Image; |
| import org.osgi.framework.*; |
| |
| public class ManifestContentAssistProcessor extends TypePackageCompletionProcessor implements ICompletionListener { |
| |
| protected PDESourcePage fSourcePage; |
| private IJavaProject fJP; |
| |
| // if we order the headers alphabetically in the array, there is no need to sort and we can save time |
| private static final String[] fHeader = { ICoreConstants.AUTOMATIC_MODULE_NAME, Constants.BUNDLE_ACTIVATIONPOLICY, Constants.BUNDLE_ACTIVATOR, Constants.BUNDLE_CATEGORY, Constants.BUNDLE_CLASSPATH, Constants.BUNDLE_CONTACTADDRESS, Constants.BUNDLE_COPYRIGHT, Constants.BUNDLE_DESCRIPTION, Constants.BUNDLE_DOCURL, Constants.BUNDLE_LOCALIZATION, Constants.BUNDLE_MANIFESTVERSION, Constants.BUNDLE_NAME, Constants.BUNDLE_NATIVECODE, Constants.BUNDLE_REQUIREDEXECUTIONENVIRONMENT, Constants.BUNDLE_SYMBOLICNAME, Constants.BUNDLE_UPDATELOCATION, Constants.BUNDLE_VENDOR, Constants.BUNDLE_VERSION, Constants.DYNAMICIMPORT_PACKAGE, ICoreConstants.ECLIPSE_BUDDY_POLICY, ICoreConstants.ECLIPSE_BUNDLE_SHAPE, ICoreConstants.ECLIPSE_EXPORT_EXTERNAL_ANNOTATIONS, ICoreConstants.ECLIPSE_GENERIC_CAPABILITY, ICoreConstants.ECLIPSE_GENERIC_REQUIRED, ICoreConstants.ECLIPSE_LAZYSTART, |
| ICoreConstants.PLATFORM_FILTER, ICoreConstants.ECLIPSE_REGISTER_BUDDY, ICoreConstants.ECLIPSE_SOURCE_REFERENCES, Constants.EXPORT_PACKAGE, ICoreConstants.EXPORT_SERVICE, Constants.FRAGMENT_HOST, Constants.IMPORT_PACKAGE, ICoreConstants.IMPORT_SERVICE, Constants.PROVIDE_CAPABILITY, Constants.REQUIRE_BUNDLE, Constants.REQUIRE_CAPABILITY}; |
| |
| |
| private static final char[] fAutoActivationChars = { ':', ' ', ',', '.', ';', '=' }; |
| |
| protected static final short F_TYPE_HEADER = 0, // header proposal |
| F_TYPE_PKG = 1, // package proposal |
| F_TYPE_BUNDLE = 2, // bundle proposal |
| F_TYPE_CLASS = 3, // class proposal |
| F_TYPE_DIRECTIVE = 4, // directive proposal |
| F_TYPE_ATTRIBUTE = 5, // attribute proposal |
| F_TYPE_VALUE = 6, // value of attribute or directive proposal |
| F_TYPE_EXEC_ENV = 7, // value of execution env., added since we use a unique icon for exec envs. |
| |
| F_TOTAL_TYPES = 8; |
| |
| private final Image[] fImages = new Image[F_TOTAL_TYPES]; |
| |
| private static final String[] fExecEnvs; |
| static { |
| IExecutionEnvironment[] envs = JavaRuntime.getExecutionEnvironmentsManager().getExecutionEnvironments(); |
| fExecEnvs = new String[envs.length]; |
| for (int i = 0; i < envs.length; i++) |
| fExecEnvs[i] = envs[i].getId(); |
| Arrays.sort(fExecEnvs, String::compareToIgnoreCase); |
| } |
| |
| /** |
| * Maps string header names to either a Set of Strings or an array of {@link ManifestElement}s. See {@link #isHeader(IDocument, int, int)} |
| */ |
| Map<String, Object> fHeaders; |
| |
| public ManifestContentAssistProcessor(PDESourcePage sourcePage) { |
| fSourcePage = sourcePage; |
| } |
| |
| @Override |
| public ICompletionProposal[] computeCompletionProposals(ITextViewer viewer, int offset) { |
| IDocument doc = fSourcePage.getDocumentProvider().getDocument(fSourcePage.getInputContext().getInput()); |
| if (fHeaders == null) { |
| parseDocument(doc); |
| } |
| try { |
| int lineNum = doc.getLineOfOffset(offset); |
| int lineStart = doc.getLineOffset(lineNum); |
| return computeCompletionProposals(doc, lineStart, offset); |
| } catch (BadLocationException e) { |
| } |
| return null; |
| } |
| |
| @Override |
| public char[] getCompletionProposalAutoActivationCharacters() { |
| return fAutoActivationChars; |
| } |
| |
| protected final void parseDocument(IDocument doc) { |
| fHeaders = new HeaderMap<>(); |
| int numLines = doc.getNumberOfLines(); |
| int offset = 0; |
| // since we are searching the line after the current line to peak ahead to see if it is a new header, start with the index of 1 |
| for (int i = 1; i < numLines; i++) { |
| try { |
| IRegion nextLine = doc.getLineInformation(i); |
| // see if the next line contains a new header. If so, we know we found the end of the current header |
| if (containsNewHeader(doc.get(nextLine.getOffset(), nextLine.getLength())) || i == (numLines - 1)) { |
| // if the next line contains a header, then get the text up to the character before the next line's offset |
| String value = doc.get(offset, nextLine.getOffset() - offset - 1).trim(); |
| int index = value.indexOf(':'); |
| String header = (index == -1) ? value : value.substring(0, index); |
| try { |
| if (value.endsWith(",")) //$NON-NLS-1$ |
| value = value.substring(0, value.length() - 1); |
| ManifestElement[] elems = ManifestElement.parseHeader(header, value.substring(index + 1)); |
| if (shouldStoreSet(header)) { |
| HashSet<String> set = new HashSet<>((4 / 3) * elems.length + 1); |
| for (ManifestElement elem : elems) |
| set.add(elem.getValue()); |
| fHeaders.put(header, set); |
| } else |
| fHeaders.put(header, elems); |
| } catch (BundleException e) { |
| } |
| offset = nextLine.getOffset(); |
| } |
| } catch (BadLocationException e) { |
| } |
| } |
| } |
| |
| private boolean containsNewHeader(String text) { |
| int length = text.length(); |
| // blank lines represent a new header as defined by the Java Manifest Specification |
| if (length == 0) |
| return true; |
| int index = text.indexOf(':'); |
| while (index != -1) { |
| // if we are at end of the line, assume it the colon is defining a new header. |
| // If the next character is an '=', the colon is part of a directive so we should continue looking |
| if ((index == length - 1) || (text.charAt(index + 1) != '=')) |
| return true; |
| index = text.indexOf(':', index + 1); |
| } |
| return false; |
| } |
| |
| protected final boolean shouldStoreSet(String header) { |
| return header.equalsIgnoreCase(Constants.IMPORT_PACKAGE) || header.equalsIgnoreCase(Constants.EXPORT_PACKAGE) || header.equalsIgnoreCase(Constants.REQUIRE_BUNDLE) || header.equalsIgnoreCase(Constants.BUNDLE_REQUIREDEXECUTIONENVIRONMENT); |
| } |
| |
| protected ICompletionProposal[] computeCompletionProposals(IDocument doc, int startOffset, int offset) { |
| try { |
| if (!isHeader(doc, startOffset, offset)) |
| return computeValue(doc, startOffset, offset); |
| return computeHeader(doc.get(startOffset, offset - startOffset), startOffset, offset); |
| } catch (BadLocationException e) { |
| } |
| return new ICompletionProposal[0]; |
| } |
| |
| protected final boolean isHeader(IDocument doc, int startOffset, int offset) throws BadLocationException { |
| String value = doc.get(startOffset, offset - startOffset); |
| if (value.indexOf(':') != -1) |
| return false; |
| for (--startOffset; startOffset >= 0; --startOffset) { |
| char ch = doc.getChar(startOffset); |
| if (!Character.isWhitespace(ch)) |
| return ch != ',' && ch != ':' && ch != ';'; |
| } |
| return true; |
| } |
| |
| protected ICompletionProposal[] computeHeader(String currentValue, int startOffset, int offset) { |
| ArrayList<TypeCompletionProposal> completions = new ArrayList<>(); |
| for (String element : fHeader) { |
| if (element.regionMatches(true, 0, currentValue, 0, currentValue.length()) && fHeaders.get(element) == null) { |
| TypeCompletionProposal proposal = new TypeCompletionProposal(element + ": ", getImage(F_TYPE_HEADER), //$NON-NLS-1$ |
| element, startOffset, currentValue.length()); |
| proposal.setAdditionalProposalInfo(getJavaDoc(element)); |
| completions.add(proposal); |
| } |
| } |
| return completions.toArray(new ICompletionProposal[completions.size()]); |
| } |
| |
| protected ICompletionProposal[] computeValue(IDocument doc, int startOffset, int offset) throws BadLocationException { |
| String value = doc.get(startOffset, offset - startOffset); |
| int lineNum = doc.getLineOfOffset(startOffset) - 1; |
| int index; |
| while ((index = value.indexOf(':')) == -1 || ((value.length() - 1 != index) && (value.charAt(index + 1) == '='))) { |
| int startLine = doc.getLineOffset(lineNum); |
| value = doc.get(startLine, offset - startLine); |
| lineNum--; |
| } |
| |
| int length = value.length(); |
| if (value.regionMatches(true, 0, Constants.IMPORT_PACKAGE, 0, Math.min(length, Constants.IMPORT_PACKAGE.length()))) |
| return handleImportPackageCompletion(value.substring(Constants.IMPORT_PACKAGE.length() + 1), offset); |
| if (value.regionMatches(true, 0, Constants.FRAGMENT_HOST, 0, Math.min(length, Constants.FRAGMENT_HOST.length()))) |
| return handleFragmentHostCompletion(value.substring(Constants.FRAGMENT_HOST.length() + 1), offset); |
| if (value.regionMatches(true, 0, Constants.REQUIRE_BUNDLE, 0, Math.min(length, Constants.REQUIRE_BUNDLE.length()))) |
| return handleRequireBundleCompletion(value.substring(Constants.REQUIRE_BUNDLE.length() + 1), offset); |
| if (value.regionMatches(true, 0, Constants.EXPORT_PACKAGE, 0, Math.min(length, Constants.EXPORT_PACKAGE.length()))) |
| return handleExportPackageCompletion(value.substring(Constants.EXPORT_PACKAGE.length() + 1), offset); |
| if (value.regionMatches(true, 0, Constants.BUNDLE_ACTIVATOR, 0, Math.min(length, Constants.BUNDLE_ACTIVATOR.length()))) |
| return handleBundleActivatorCompletion(removeLeadingSpaces(value.substring(Constants.BUNDLE_ACTIVATOR.length() + 1)), offset); |
| if (value.regionMatches(true, 0, Constants.BUNDLE_SYMBOLICNAME, 0, Math.min(length, Constants.BUNDLE_SYMBOLICNAME.length()))) |
| return handleBundleSymbolicNameCompletion(value.substring(Constants.BUNDLE_SYMBOLICNAME.length() + 1), offset); |
| if (value.regionMatches(true, 0, Constants.BUNDLE_REQUIREDEXECUTIONENVIRONMENT, 0, Math.min(length, Constants.BUNDLE_REQUIREDEXECUTIONENVIRONMENT.length()))) |
| return handleRequiredExecEnv(value.substring(Constants.BUNDLE_REQUIREDEXECUTIONENVIRONMENT.length() + 1), offset); |
| if (value.regionMatches(true, 0, ICoreConstants.ECLIPSE_LAZYSTART, 0, Math.min(length, ICoreConstants.ECLIPSE_LAZYSTART.length()))) |
| return handleTrueFalseValue(value.substring(ICoreConstants.ECLIPSE_LAZYSTART.length() + 1), offset); |
| if (value.regionMatches(true, 0, Constants.BUNDLE_NAME, 0, Math.min(length, Constants.BUNDLE_NAME.length()))) |
| return handleBundleNameCompletion(value.substring(Constants.BUNDLE_NAME.length() + 1), offset); |
| if (value.regionMatches(true, 0, Constants.BUNDLE_ACTIVATIONPOLICY, 0, Math.min(length, Constants.BUNDLE_ACTIVATIONPOLICY.length()))) |
| return handleBundleActivationPolicyCompletion(value.substring(Constants.BUNDLE_ACTIVATIONPOLICY.length() + 1), offset); |
| if (value.regionMatches(true, 0, ICoreConstants.ECLIPSE_BUDDY_POLICY, 0, Math.min(length, ICoreConstants.ECLIPSE_BUDDY_POLICY.length()))) |
| return handleBuddyPolicyCompletion(value.substring(ICoreConstants.ECLIPSE_BUDDY_POLICY.length() + 1), offset); |
| if (value.regionMatches(true, 0, ICoreConstants.ECLIPSE_BUNDLE_SHAPE, 0, Math.min(length, ICoreConstants.ECLIPSE_BUNDLE_SHAPE.length()))) |
| return handleEclipseBundleShape(value.substring(ICoreConstants.ECLIPSE_BUNDLE_SHAPE.length() + 1), offset); |
| if (value.regionMatches(true, 0, ICoreConstants.ECLIPSE_EXPORT_EXTERNAL_ANNOTATIONS, 0, |
| Math.min(length, ICoreConstants.ECLIPSE_EXPORT_EXTERNAL_ANNOTATIONS.length()))) |
| return handleTrueFalseValue( |
| value.substring(ICoreConstants.ECLIPSE_EXPORT_EXTERNAL_ANNOTATIONS.length() + 1), offset); |
| return new ICompletionProposal[0]; |
| } |
| |
| /* |
| * Easter Egg |
| */ |
| protected ICompletionProposal[] handleBundleNameCompletion(String currentValue, int offset) { |
| currentValue = removeLeadingSpaces(currentValue); |
| return new ICompletionProposal[0]; |
| } |
| |
| protected ICompletionProposal[] handleImportPackageCompletion(String currentValue, int offset) { |
| int comma = currentValue.lastIndexOf(','); |
| int semicolon = currentValue.lastIndexOf(';'); |
| String value = comma != -1 ? currentValue.substring(comma + 1) : currentValue; |
| if (comma > semicolon || comma == semicolon) { |
| @SuppressWarnings("unchecked") |
| HashSet<String> set = (HashSet<String>) fHeaders.get(Constants.IMPORT_PACKAGE); |
| if (set == null) |
| set = parseHeaderForValues(currentValue, offset); |
| @SuppressWarnings("unchecked") |
| HashSet<String> importedBundles = (HashSet<String>) fHeaders.get(Constants.REQUIRE_BUNDLE); |
| if (importedBundles == null) |
| importedBundles = new HashSet<>(0); |
| value = removeLeadingSpaces(value); |
| int length = value.length(); |
| set.remove(value); |
| ArrayList<TypeCompletionProposal> completions = new ArrayList<>(); |
| IPluginModelBase[] bases = PluginRegistry.getActiveModels(); |
| |
| for (IPluginModelBase base : bases) { // Remove any packages already imported through Require-Bundle |
| BundleDescription desc = base.getBundleDescription(); |
| if (desc == null || importedBundles.contains(desc.getSymbolicName())) |
| continue; |
| ExportPackageDescription[] expPkgs = desc.getExportPackages(); |
| for (ExportPackageDescription expPkg : expPkgs) { |
| String pkgName = expPkg.getName(); |
| if (pkgName.regionMatches(true, 0, value, 0, length) && !set.contains(pkgName)) { |
| completions.add(new TypeCompletionProposal(pkgName, getImage(F_TYPE_PKG), pkgName, offset - length, length)); |
| set.add(pkgName); |
| } |
| } |
| } |
| ICompletionProposal[] proposals = completions.toArray(new ICompletionProposal[completions.size()]); |
| sortCompletions(proposals); |
| return proposals; |
| } |
| int equals = currentValue.lastIndexOf('='); |
| if (equals == -1 || semicolon > equals) { |
| String[] validAtts = new String[] {Constants.RESOLUTION_DIRECTIVE, Constants.VERSION_ATTRIBUTE}; |
| Integer[] validTypes = new Integer[] {Integer.valueOf(F_TYPE_DIRECTIVE), Integer.valueOf(F_TYPE_ATTRIBUTE)}; |
| return handleAttrsAndDirectives(value, initializeNewList(validAtts), initializeNewList(validTypes), offset); |
| } |
| String attributeValue = removeLeadingSpaces(currentValue.substring(semicolon + 1)); |
| if (Constants.RESOLUTION_DIRECTIVE.regionMatches(true, 0, attributeValue, 0, Constants.RESOLUTION_DIRECTIVE.length())) |
| return matchValueCompletion(currentValue.substring(equals + 1), new String[] {Constants.RESOLUTION_MANDATORY, Constants.RESOLUTION_OPTIONAL}, new int[] {F_TYPE_VALUE, F_TYPE_VALUE}, offset, "RESOLUTION_"); //$NON-NLS-1$ |
| if (Constants.VERSION_ATTRIBUTE.regionMatches(true, 0, attributeValue, 0, Constants.VERSION_ATTRIBUTE.length())) { |
| value = removeLeadingSpaces(currentValue.substring(equals + 1)); |
| if (value.length() == 0) |
| return new ICompletionProposal[] {new TypeCompletionProposal("\"\"", getImage(F_TYPE_VALUE), "\"\"", offset, 0)}; //$NON-NLS-1$ //$NON-NLS-2$ |
| } |
| return new ICompletionProposal[0]; |
| } |
| |
| private ICompletionProposal[] handleXFriendsCompletion(String value, final int offset) { |
| ManifestElement[] elems = (ManifestElement[]) fHeaders.get(Constants.BUNDLE_SYMBOLICNAME); |
| HashSet<String> set = new HashSet<>(); |
| if (elems != null && elems.length > 0) |
| set.add(elems[0].getValue()); |
| value = removeLeadingSpaces(value); |
| if (value.length() == 0) |
| return new ICompletionProposal[] {new TypeCompletionProposal("\"\"", getImage(F_TYPE_VALUE), "\"\"", offset, 0)}; //$NON-NLS-1$ //$NON-NLS-2$ |
| if (value.charAt(0) == '"') |
| value = value.substring(1); |
| int index = value.lastIndexOf(','); |
| StringTokenizer tokenizer = new StringTokenizer(value, ","); //$NON-NLS-1$ |
| while (tokenizer.hasMoreTokens()) |
| set.add(tokenizer.nextToken()); |
| return handleBundleCompletions(value.substring((index == -1) ? 0 : index + 1), set, F_TYPE_VALUE, offset, true); |
| } |
| |
| protected ICompletionProposal[] handleFragmentHostCompletion(String currentValue, int offset) { |
| int index = currentValue.lastIndexOf(';'); |
| if (index == -1) { |
| HashMap<String, TypeCompletionProposal> completions = new HashMap<>(); |
| IPluginModelBase base = PluginRegistry.findModel(((ManifestEditor) fSourcePage.getEditor()).getCommonProject()); |
| BundleDescription desc = base.getBundleDescription(); |
| String currentId = desc != null ? desc.getSymbolicName() : null; |
| |
| String pluginStart = removeLeadingSpaces(currentValue); |
| int length = pluginStart.length(); |
| IPluginModelBase[] bases = PluginRegistry.getActiveModels(); |
| for (IPluginModelBase base2 : bases) { |
| desc = base2.getBundleDescription(); |
| if (desc != null && desc.getHost() == null) { |
| String pluginID = base2.getBundleDescription().getSymbolicName(); |
| if (!completions.containsKey(pluginID) && pluginID.regionMatches(true, 0, pluginStart, 0, length) && !pluginID.equals(currentId)) |
| completions.put(pluginID, new TypeCompletionProposal(pluginID, getImage(F_TYPE_BUNDLE), pluginID, offset - length, length)); |
| } |
| } |
| return completions.values().toArray(new ICompletionProposal[completions.size()]); |
| } |
| int equals = currentValue.lastIndexOf('='); |
| if (equals == -1 || index > equals) |
| return matchValueCompletion(removeLeadingSpaces(currentValue.substring(index + 1)), new String[] {Constants.BUNDLE_VERSION_ATTRIBUTE}, new int[] {F_TYPE_ATTRIBUTE}, offset); |
| String attributeValue = removeLeadingSpaces(currentValue.substring(index + 1)); |
| if (Constants.BUNDLE_VERSION_ATTRIBUTE.regionMatches(true, 0, attributeValue, 0, Constants.BUNDLE_VERSION_ATTRIBUTE.length())) { |
| return getBundleVersionCompletions(currentValue.substring(0, index).trim(), removeLeadingSpaces(currentValue.substring(equals + 1)), offset); |
| } |
| return new ICompletionProposal[0]; |
| } |
| |
| protected ICompletionProposal[] handleRequireBundleCompletion(String currentValue, int offset) { |
| int comma = currentValue.lastIndexOf(','); |
| int semicolon = currentValue.lastIndexOf(';'); |
| String value = comma != -1 ? currentValue.substring(comma + 1) : currentValue; |
| if (comma > semicolon || comma == semicolon) { |
| @SuppressWarnings("unchecked") |
| HashSet<String> set = (HashSet<String>) fHeaders.get(Constants.REQUIRE_BUNDLE); |
| if (set == null) |
| set = parseHeaderForValues(currentValue, offset); |
| return handleBundleCompletions(value, set, F_TYPE_BUNDLE, offset, false); |
| } |
| int equals = currentValue.lastIndexOf('='); |
| if (equals == -1 || semicolon > equals) { |
| String[] validAttrs = new String[] {Constants.BUNDLE_VERSION_ATTRIBUTE, Constants.RESOLUTION_DIRECTIVE, Constants.VISIBILITY_DIRECTIVE}; |
| Integer[] validTypes = new Integer[] {Integer.valueOf(F_TYPE_ATTRIBUTE), Integer.valueOf(F_TYPE_DIRECTIVE), Integer.valueOf(F_TYPE_DIRECTIVE)}; |
| return handleAttrsAndDirectives(value, initializeNewList(validAttrs), initializeNewList(validTypes), offset); |
| } |
| String attributeValue = removeLeadingSpaces(currentValue.substring(semicolon + 1)); |
| if (Constants.VISIBILITY_DIRECTIVE.regionMatches(true, 0, attributeValue, 0, Constants.VISIBILITY_DIRECTIVE.length())) |
| return matchValueCompletion(currentValue.substring(equals + 1), new String[] {Constants.VISIBILITY_PRIVATE, Constants.VISIBILITY_REEXPORT}, new int[] {F_TYPE_VALUE, F_TYPE_VALUE}, offset, "VISIBILITY_"); //$NON-NLS-1$ |
| if (Constants.RESOLUTION_DIRECTIVE.regionMatches(true, 0, attributeValue, 0, Constants.RESOLUTION_DIRECTIVE.length())) |
| return matchValueCompletion(currentValue.substring(equals + 1), new String[] {Constants.RESOLUTION_MANDATORY, Constants.RESOLUTION_OPTIONAL}, new int[] {F_TYPE_VALUE, F_TYPE_VALUE}, offset, "RESOLUTION_"); //$NON-NLS-1$ |
| if (Constants.BUNDLE_VERSION_ATTRIBUTE.regionMatches(true, 0, attributeValue, 0, Constants.RESOLUTION_DIRECTIVE.length())) { |
| String pluginId = removeLeadingSpaces(currentValue.substring((comma == -1) ? 0 : comma + 1, semicolon)); |
| return getBundleVersionCompletions(pluginId, removeLeadingSpaces(currentValue.substring(equals + 1)), offset); |
| } |
| return new ICompletionProposal[0]; |
| } |
| |
| private ICompletionProposal[] getBundleVersionCompletions(String pluginID, String existingValue, int offset) { |
| ModelEntry entry = PluginRegistry.findEntry(pluginID); |
| if (entry != null) { |
| IPluginModelBase[] hosts = entry.getActiveModels(); |
| ArrayList<TypeCompletionProposal> proposals = new ArrayList<>(hosts.length); |
| for (IPluginModelBase host : hosts) { |
| String proposalValue = getVersionProposal(host); |
| if (proposalValue.regionMatches(0, existingValue, 0, existingValue.length())) |
| proposals.add(new TypeCompletionProposal(proposalValue.substring(existingValue.length()), getImage(F_TYPE_VALUE), proposalValue, offset, 0)); |
| } |
| return proposals.toArray(new ICompletionProposal[proposals.size()]); |
| } else if (existingValue.length() == 0) |
| return new ICompletionProposal[] {new TypeCompletionProposal("\"\"", getImage(F_TYPE_VALUE), "\"\"", offset, 0)}; //$NON-NLS-1$ //$NON-NLS-2$ |
| return new ICompletionProposal[0]; |
| } |
| |
| private String getVersionProposal(IPluginModelBase base) { |
| StringBuilder buffer = new StringBuilder("\""); //$NON-NLS-1$ |
| BundleDescription desc = base.getBundleDescription(); |
| if (desc != null) { |
| Version version = desc.getVersion(); |
| buffer.append(version.getMajor()); |
| buffer.append('.'); |
| buffer.append(version.getMinor()); |
| buffer.append('.'); |
| buffer.append(version.getMicro()); |
| } else { |
| char[] chars = base.getPluginBase().getVersion().toCharArray(); |
| int periodCount = 0; |
| for (char c : chars) { |
| if (c == '.') { |
| if (periodCount == 2) |
| break; |
| ++periodCount; |
| } |
| buffer.append(c); |
| } |
| } |
| return buffer.append('\"').toString(); |
| } |
| |
| private ICompletionProposal[] handleBundleCompletions(String value, Collection<String> doNotInclude, int type, int offset, boolean includeFragments) { |
| value = removeLeadingSpaces(value); |
| int length = value.length(); |
| doNotInclude.remove(value); |
| ArrayList<TypeCompletionProposal> completions = new ArrayList<>(); |
| IPluginModelBase[] bases = PluginRegistry.getActiveModels(); |
| for (IPluginModelBase base : bases) { |
| BundleDescription desc = base.getBundleDescription(); |
| if (desc != null) { |
| if (!includeFragments && desc.getHost() != null) |
| continue; |
| String bundleId = desc.getSymbolicName(); |
| if (bundleId.regionMatches(true, 0, value, 0, value.length()) && !doNotInclude.contains(bundleId)) |
| completions.add(new TypeCompletionProposal(bundleId, getImage(type), bundleId, offset - length, length)); |
| } |
| } |
| return completions.toArray(new ICompletionProposal[completions.size()]); |
| } |
| |
| protected ICompletionProposal[] handleExportPackageCompletion(String currentValue, int offset) { |
| int comma = currentValue.lastIndexOf(','); |
| int semicolon = currentValue.lastIndexOf(';'); |
| ArrayList<TypeCompletionProposal> list = new ArrayList<>(); |
| if (!insideQuotes(currentValue) && comma > semicolon || comma == semicolon) { |
| String value = comma != -1 ? currentValue.substring(comma + 1) : currentValue; |
| @SuppressWarnings("unchecked") |
| HashSet<String> set = (HashSet<String>) fHeaders.get(Constants.EXPORT_PACKAGE); |
| if (set == null) |
| set = parseHeaderForValues(currentValue, offset); |
| value = removeLeadingSpaces(value); |
| addPackageCompletions(value, set, offset, list); |
| } else { |
| String value = currentValue; |
| if (comma > 0) { |
| do { |
| String prefix = currentValue.substring(0, comma); |
| if (!insideQuotes(prefix)) { |
| value = currentValue.substring(comma + 1); |
| break; |
| } |
| comma = currentValue.lastIndexOf(',', comma - 1); |
| } while (comma > 0); |
| } |
| int equals = currentValue.lastIndexOf('='); |
| if (equals == -1 || semicolon > equals) { |
| String[] validAttrs = new String[] {Constants.VERSION_ATTRIBUTE, ICoreConstants.INTERNAL_DIRECTIVE, ICoreConstants.FRIENDS_DIRECTIVE}; |
| Integer[] validTypes = new Integer[] {Integer.valueOf(F_TYPE_ATTRIBUTE), Integer.valueOf(F_TYPE_DIRECTIVE), Integer.valueOf(F_TYPE_DIRECTIVE)}; |
| return handleAttrsAndDirectives(value, initializeNewList(validAttrs), initializeNewList(validTypes), offset); |
| } |
| String attributeValue = removeLeadingSpaces(currentValue.substring(semicolon + 1)); |
| if (ICoreConstants.FRIENDS_DIRECTIVE.regionMatches(true, 0, attributeValue, 0, ICoreConstants.FRIENDS_DIRECTIVE.length())) |
| return handleXFriendsCompletion(currentValue.substring(equals + 1), offset); |
| if (ICoreConstants.INTERNAL_DIRECTIVE.regionMatches(true, 0, attributeValue, 0, ICoreConstants.INTERNAL_DIRECTIVE.length())) |
| return handleTrueFalseValue(currentValue.substring(equals + 1), offset); |
| if (Constants.VERSION_ATTRIBUTE.regionMatches(true, 0, attributeValue, 0, Constants.VERSION_ATTRIBUTE.length())) { |
| value = removeLeadingSpaces(currentValue.substring(equals + 1)); |
| if (value.length() == 0) |
| return new ICompletionProposal[] {new TypeCompletionProposal("\"\"", getImage(F_TYPE_VALUE), "\"\"", offset, 0)}; //$NON-NLS-1$ //$NON-NLS-2$ |
| } |
| } |
| return list.toArray(new ICompletionProposal[list.size()]); |
| } |
| |
| protected ICompletionProposal[] handleBundleActivatorCompletion(final String currentValue, final int offset) { |
| ArrayList<Object> completions = new ArrayList<>(); |
| IProject project = ((PDEFormEditor) fSourcePage.getEditor()).getCommonProject(); |
| int startOffset = offset - currentValue.length(); |
| generateTypePackageProposals(currentValue, project, completions, startOffset, IJavaSearchConstants.CLASS); |
| ICompletionProposal[] proposals = completions.toArray(new ICompletionProposal[completions.size()]); |
| sortCompletions(proposals); |
| return proposals; |
| } |
| |
| protected ICompletionProposal[] handleBundleSymbolicNameCompletion(String currentValue, int offset) { |
| int semicolon = currentValue.indexOf(';'); |
| if (semicolon != -1) { |
| int equals = currentValue.indexOf('='); |
| if (equals == -1) { |
| String attribute = currentValue.substring(semicolon + 1); |
| attribute = removeLeadingSpaces(attribute); |
| Object o = fHeaders.get(Constants.BUNDLE_MANIFESTVERSION); |
| int type = (o == null || o.toString().equals("1")) ? F_TYPE_ATTRIBUTE : F_TYPE_DIRECTIVE;//$NON-NLS-1$ |
| if (Constants.SINGLETON_DIRECTIVE.regionMatches(true, 0, attribute, 0, attribute.length())) { |
| int length = attribute.length(); |
| TypeCompletionProposal proposal = new TypeCompletionProposal(Constants.SINGLETON_DIRECTIVE + ":=", //$NON-NLS-1$ |
| getImage(type), Constants.SINGLETON_DIRECTIVE, offset - length, length); |
| proposal.setAdditionalProposalInfo(getJavaDoc("SINGLETON_DIRECTIVE")); //$NON-NLS-1$ |
| return new ICompletionProposal[] {proposal}; |
| } |
| } else if (equals > semicolon) |
| return handleTrueFalseValue(currentValue.substring(equals + 1), offset); |
| } |
| return new ICompletionProposal[0]; |
| } |
| |
| protected ICompletionProposal[] handleBundleActivationPolicyCompletion(final String currentValue, final int offset) { |
| int semicolon = currentValue.lastIndexOf(';'); |
| if (semicolon == -1) { |
| // we know there are no directives, therefore we are looking for a header value |
| String value = removeLeadingSpaces(currentValue); |
| String lazyValue = Constants.ACTIVATION_LAZY; |
| int length = value.length(); |
| if (lazyValue.regionMatches(0, value, 0, length)) |
| return new ICompletionProposal[] {new TypeCompletionProposal(lazyValue, null, lazyValue, offset - length, length)}; |
| } else { |
| int equals = currentValue.lastIndexOf('='); |
| if (semicolon > equals) { |
| // we know we are looking for a directive |
| String[] validDirectives = new String[] {Constants.EXCLUDE_DIRECTIVE, Constants.INCLUDE_DIRECTIVE}; |
| Integer[] validTypes = new Integer[] {Integer.valueOf(F_TYPE_DIRECTIVE), Integer.valueOf(F_TYPE_DIRECTIVE)}; |
| return handleAttrsAndDirectives(currentValue, initializeNewList(validDirectives), initializeNewList(validTypes), offset); |
| } |
| int quote = currentValue.lastIndexOf('"'); |
| if (!insideQuotes(currentValue)) { |
| // if quote > equals, that means the cursor is after a closing quote for the directive |
| if (equals > quote) |
| return new ICompletionProposal[] {new TypeCompletionProposal("\"\"", getImage(F_TYPE_VALUE), "\"\"", offset, 0)}; //$NON-NLS-1$ //$NON-NLS-2$ |
| } else { |
| // We know we are looking for a completion inside the quote of a directive |
| String value = currentValue.substring(quote + 1); |
| // find existing packages |
| StringTokenizer parser = new StringTokenizer(value, ","); //$NON-NLS-1$ |
| HashSet<String> set = new HashSet<>(); |
| while (parser.hasMoreTokens()) { |
| set.add(parser.nextToken().trim()); |
| } |
| // find the value of the package we are trying to find the completion for |
| int comma = value.lastIndexOf(','); |
| if (comma > -1) |
| value = removeLeadingSpaces(value.substring(comma + 1)); |
| // find proposals |
| ArrayList<TypeCompletionProposal> proposals = new ArrayList<>(); |
| addPackageCompletions(value, set, offset, proposals); |
| return proposals.toArray(new ICompletionProposal[proposals.size()]); |
| } |
| } |
| return new ICompletionProposal[0]; |
| } |
| |
| protected ICompletionProposal[] handleBuddyPolicyCompletion(String currentValue, int offset) { |
| String[] validValues = new String[] {"dependent", "global", "registered", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ |
| "app", "ext", "boot", "parent"}; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ |
| |
| int comma = currentValue.lastIndexOf(','); |
| if (comma != -1) |
| currentValue = currentValue.substring(comma + 1); |
| currentValue = removeLeadingSpaces(currentValue); |
| ArrayList<TypeCompletionProposal> completions = new ArrayList<>(); |
| ManifestElement[] elems = (ManifestElement[]) fHeaders.get(ICoreConstants.ECLIPSE_BUDDY_POLICY); |
| HashSet<String> set = new HashSet<>(); |
| if (elems != null) |
| for (ManifestElement elem : elems) |
| set.add(elem.getValue()); |
| int length = currentValue.length(); |
| for (int i = 0; i < validValues.length; i++) |
| if (validValues[i].regionMatches(true, 0, currentValue, 0, length) && !set.contains(validValues[i])) |
| completions.add(new TypeCompletionProposal(validValues[i], getImage(F_TYPE_VALUE), validValues[i], offset - length, length)); |
| return completions.toArray(new ICompletionProposal[completions.size()]); |
| } |
| |
| protected ICompletionProposal[] handleRequiredExecEnv(String currentValue, int offset) { |
| int comma = currentValue.lastIndexOf(','); |
| if (comma != -1) |
| currentValue = currentValue.substring(comma + 1); |
| currentValue = removeLeadingSpaces(currentValue); |
| ArrayList<TypeCompletionProposal> completions = new ArrayList<>(); |
| @SuppressWarnings("unchecked") |
| HashSet<String> set = (HashSet<String>) fHeaders.get(Constants.BUNDLE_REQUIREDEXECUTIONENVIRONMENT); |
| if (set == null) |
| set = new HashSet<>(0); |
| int length = currentValue.length(); |
| for (int i = 0; i < fExecEnvs.length; i++) |
| if (fExecEnvs[i].regionMatches(true, 0, currentValue, 0, length) && !set.contains(fExecEnvs[i])) |
| completions.add(new TypeCompletionProposal(fExecEnvs[i], getImage(F_TYPE_EXEC_ENV), fExecEnvs[i], offset - length, length)); |
| return completions.toArray(new ICompletionProposal[completions.size()]); |
| } |
| |
| protected ICompletionProposal[] handleTrueFalseValue(String currentValue, int offset) { |
| currentValue = removeLeadingSpaces(currentValue); |
| int length = currentValue.length(); |
| if (length == 0) |
| return new ICompletionProposal[] {new TypeCompletionProposal("true", getImage(F_TYPE_VALUE), "true", offset, 0), //$NON-NLS-1$ //$NON-NLS-2$ |
| new TypeCompletionProposal("false", getImage(F_TYPE_VALUE), "false", offset, 0) //$NON-NLS-1$ //$NON-NLS-2$ |
| }; |
| else if (length < 5 && "true".regionMatches(true, 0, currentValue, 0, length)) //$NON-NLS-1$ |
| return new ICompletionProposal[] {new TypeCompletionProposal("true", getImage(F_TYPE_VALUE), "true", offset - length, length) //$NON-NLS-1$ //$NON-NLS-2$ |
| }; |
| else if (length < 6 && "false".regionMatches(true, 0, currentValue, 0, length)) //$NON-NLS-1$ |
| return new ICompletionProposal[] {new TypeCompletionProposal("false", getImage(F_TYPE_VALUE), "false", offset - length, length) //$NON-NLS-1$ //$NON-NLS-2$ |
| }; |
| return new ICompletionProposal[0]; |
| } |
| |
| protected ICompletionProposal[] handleEclipseBundleShape(String currentValue, int offset) { |
| currentValue = removeLeadingSpaces(currentValue); |
| ArrayList<TypeCompletionProposal> completions = new ArrayList<>(); |
| int length = currentValue.length(); |
| String[] values = ICoreConstants.SHAPE_VALUES; |
| for (int i = 0; i < values.length; i++) |
| if (values[i].regionMatches(true, 0, currentValue, 0, length) && !currentValue.equals(values[i])) |
| completions.add(new TypeCompletionProposal(values[i], getImage(F_TYPE_VALUE), values[i], offset - length, length)); |
| return completions.toArray(new ICompletionProposal[completions.size()]); |
| } |
| |
| protected ICompletionProposal[] matchValueCompletion(String value, String[] attrs, int[] types, int offset) { |
| return matchValueCompletion(value, attrs, types, offset, ""); //$NON-NLS-1$ |
| } |
| |
| protected ICompletionProposal[] matchValueCompletion(String value, String[] attrs, int[] types, int offset, String prefixCostant) { |
| ArrayList<TypeCompletionProposal> list = new ArrayList<>(); |
| int length = value.length(); |
| TypeCompletionProposal proposal = null; |
| for (int i = 0; i < attrs.length; i++) |
| if (attrs[i].regionMatches(true, 0, value, 0, length)) { |
| switch (types[i]) |
| { |
| case F_TYPE_ATTRIBUTE: |
| proposal = new TypeCompletionProposal(attrs[i] + "=", getImage(F_TYPE_ATTRIBUTE), attrs[i], //$NON-NLS-1$ |
| offset - length, length); |
| proposal.setAdditionalProposalInfo(getJavaDoc(attrs[i] + "_ATTRIBUTE")); //$NON-NLS-1$ |
| break; |
| case F_TYPE_DIRECTIVE: |
| proposal = new TypeCompletionProposal(attrs[i] + ":=", getImage(F_TYPE_DIRECTIVE), attrs[i], //$NON-NLS-1$ |
| offset - length, length); |
| proposal.setAdditionalProposalInfo(getJavaDoc(attrs[i] + "_DIRECTIVE")); //$NON-NLS-1$ |
| break; |
| default: |
| proposal = new TypeCompletionProposal(attrs[i], getImage(types[i]), attrs[i], offset - length, |
| length); |
| proposal.setAdditionalProposalInfo(getJavaDoc(prefixCostant + attrs[i])); |
| break; |
| } |
| list.add(proposal); |
| } |
| return list.toArray(new ICompletionProposal[list.size()]); |
| } |
| |
| protected ICompletionProposal[] handleAttrsAndDirectives(String value, ArrayList<Object> attrs, ArrayList<Object> types, int offset) { |
| String fullValue = findFullLine(value, offset, false); |
| int semicolon = value.lastIndexOf(';'); |
| value = removeLeadingSpaces(value.substring(semicolon + 1)); |
| StringTokenizer tokenizer = new StringTokenizer(fullValue, ";"); //$NON-NLS-1$ |
| // remove value part of the String, the rest of the tokens will be attributes/directives |
| tokenizer.nextToken(); |
| while (tokenizer.hasMoreTokens()) { |
| String tokenValue = removeLeadingSpaces(tokenizer.nextToken()); |
| int index = tokenValue.indexOf('='); |
| if (index == -1) |
| continue; |
| if (tokenValue.charAt(index - 1) == ':') |
| --index; |
| tokenValue = tokenValue.substring(0, index); |
| int indexOfObject = attrs.indexOf(tokenValue); |
| if (indexOfObject >= 0) { |
| attrs.remove(indexOfObject); |
| types.remove(indexOfObject); |
| } |
| } |
| return matchValueCompletion(value, attrs.toArray(new String[attrs.size()]), toIntArray(types), offset); |
| } |
| |
| /** |
| * Adds completions to the proposals list which represent packages in source folders found in the current project |
| * |
| * @param value the current incomplete package value (without any leading spaces) |
| * @param currentPackages a Set containing the packages already specified by the Manifest Header |
| * @param offset the offset of the current completion proposal |
| * @param proposals the list to which new completion proposals will be added |
| */ |
| private void addPackageCompletions(String value, Set<String> currentPackages, int offset, ArrayList<TypeCompletionProposal> proposals) { |
| int length = value.length(); |
| IProject proj = ((PDEFormEditor) fSourcePage.getEditor()).getCommonProject(); |
| if (proj != null) { |
| IJavaProject jp = JavaCore.create(proj); |
| IPackageFragment[] frags = PDEJavaHelper.getPackageFragments(jp, currentPackages, false); |
| for (IPackageFragment frag : frags) { |
| String name = frag.getElementName(); |
| if (name.regionMatches(true, 0, value, 0, length)) |
| proposals.add(new TypeCompletionProposal(name, getImage(F_TYPE_PKG), name, offset - length, length)); |
| } |
| } |
| } |
| |
| private HashSet<String> parseHeaderForValues(String currentValue, int offset) { |
| HashSet<String> set = new HashSet<>(); |
| String fullValue = findFullLine(currentValue, offset, true); |
| StringTokenizer tokenizer = new StringTokenizer(fullValue, ","); //$NON-NLS-1$ |
| while (tokenizer.hasMoreTokens()) { |
| String pkgValue = tokenizer.nextToken(); |
| int index = pkgValue.indexOf(';'); |
| set.add(index == -1 ? pkgValue.trim() : pkgValue.substring(0, index).trim()); |
| } |
| return set; |
| } |
| |
| private String findFullLine(String value, int offset, boolean entireHeader) { |
| IDocument doc = fSourcePage.getDocumentProvider().getDocument(fSourcePage.getInputContext().getInput()); |
| try { |
| int line = doc.getLineOfOffset(offset); |
| String newValue = ""; //$NON-NLS-1$ |
| int startOfLine = 0; |
| int colon = -1; |
| do { |
| startOfLine = doc.getLineOffset(line); |
| newValue = doc.get(offset, doc.getLineLength(line) - offset + startOfLine); |
| ++line; |
| colon = newValue.lastIndexOf(':'); |
| } while ((colon == -1 || (newValue.length() > colon && newValue.charAt(colon + 1) == '=')) && (entireHeader || newValue.indexOf(',') == -1) && !(doc.getNumberOfLines() == line)); |
| |
| if (colon > 0 && newValue.charAt(colon + 1) != '=') { |
| newValue = doc.get(offset, startOfLine - 1 - offset); |
| } else { |
| // break on the comma to find our element, but only break on a comma that is not enclosed in parenthesis |
| int comma = newValue.indexOf(','); |
| int parenthesis = newValue.indexOf('"'); |
| if (!(parenthesis < comma && newValue.indexOf('"', parenthesis + 1) > comma)) |
| newValue = (comma != -1) ? newValue.substring(0, comma) : newValue; |
| } |
| return value.concat(newValue); |
| } catch (BadLocationException e) { |
| } |
| return ""; //$NON-NLS-1$ |
| } |
| |
| private int[] toIntArray(ArrayList<Object> list) { |
| int[] result = new int[list.size()]; |
| int i = -1; |
| while (++i < result.length) { |
| Object o = list.get(i); |
| if (!(o instanceof Integer)) |
| return new int[0]; |
| result[i] = ((Integer) o).intValue(); |
| } |
| return result; |
| } |
| |
| // if you use java.util.Arrays.asList(), we get an UnsupportedOperation later in the code |
| protected final ArrayList<Object> initializeNewList(Object[] values) { |
| ArrayList<Object> list = new ArrayList<>(values.length); |
| Collections.addAll(list, values); |
| return list; |
| } |
| |
| private boolean insideQuotes(String value) { |
| char[] chars = value.toCharArray(); |
| int numOfQuotes = 0; |
| for (char c : chars) |
| if (c == '\"') |
| ++numOfQuotes; |
| int j = numOfQuotes % 2; |
| return j == 1; |
| } |
| |
| @Override |
| public void assistSessionEnded(ContentAssistEvent event) { |
| fHeaders = null; |
| } |
| |
| @Override |
| public void assistSessionStarted(ContentAssistEvent event) { |
| } |
| |
| @Override |
| public void selectionChanged(ICompletionProposal proposal, boolean smartToggle) { |
| } |
| |
| public Image getImage(int type) { |
| if (type >= 0 && type < F_TOTAL_TYPES) |
| if (fImages[type] == null) { |
| switch (type) { |
| case F_TYPE_HEADER : |
| return fImages[type] = PDEPluginImages.DESC_BUILD_VAR_OBJ.createImage(); |
| case F_TYPE_PKG : |
| return PDEPluginImages.get(PDEPluginImages.OBJ_DESC_PACKAGE); |
| case F_TYPE_BUNDLE : |
| return fImages[type] = PDEPluginImages.DESC_PLUGIN_OBJ.createImage(); |
| case F_TYPE_CLASS : |
| return PDEPluginImages.get(PDEPluginImages.OBJ_DESC_GENERATE_CLASS); |
| case F_TYPE_ATTRIBUTE : |
| return fImages[type] = PDEPluginImages.DESC_ATT_URI_OBJ.createImage(); |
| case F_TYPE_DIRECTIVE : |
| fImages[F_TYPE_ATTRIBUTE] = PDEPluginImages.DESC_ATT_URI_OBJ.createImage(); |
| ImageOverlayIcon icon = new ImageOverlayIcon(fImages[F_TYPE_ATTRIBUTE], new ImageDescriptor[][] {new ImageDescriptor[] {PDEPluginImages.DESC_DOC_CO}, null, null, null}); |
| return fImages[type] = icon.createImage(); |
| case F_TYPE_EXEC_ENV : |
| return fImages[type] = PDEPluginImages.DESC_JAVA_LIB_OBJ.createImage(); |
| case F_TYPE_VALUE : |
| return null; |
| } |
| } else |
| return fImages[type]; |
| return null; |
| } |
| |
| public void dispose() { |
| for (int i = 0; i < fImages.length; i++) |
| if (fImages[i] != null && !fImages[i].isDisposed()) |
| fImages[i].dispose(); |
| } |
| |
| private String getJavaDoc(String constant) { |
| if (fJP == null) { |
| IProject project = ((PDEFormEditor) fSourcePage.getEditor()).getCommonProject(); |
| fJP = JavaCore.create(project); |
| } |
| return PDEJavaHelperUI.getOSGIConstantJavaDoc(constant, fJP); |
| } |
| |
| } |