View | Details | Raw Unified | Return to bug 88204 | Differences between
and this patch

Collapse All | Expand All

(-)plugin.xml (+15 lines)
Lines 1760-1763 Link Here
1760
                id="org.eclipse.jdt.ui.text.correction.QuickFixProcessor">
1760
                id="org.eclipse.jdt.ui.text.correction.QuickFixProcessor">
1761
          </quickFixProcessor>
1761
          </quickFixProcessor>
1762
       </extension>
1762
       </extension>
1763
       <extension
1764
             point="org.eclipse.jdt.ui.classpathFixProcessors">
1765
          <classpathFixProcessor
1766
                class="org.eclipse.pde.internal.ui.correction.java.UnresolvedImportFixProcessor"
1767
                id="org.eclipse.pde.ui.unresolvedImportQuickFixProcessor"
1768
                name="Unresolved Import Quick Fix Processor">
1769
                <enablement>
1770
                   <with variable="project">
1771
		              <test property="org.eclipse.jdt.core.isInJavaProjectWithNature" value="org.eclipse.pde.PluginNature"/>
1772
                   </with>
1773
                </enablement>
1774
                <overrides id="org.eclipse.jdt.ui.text.correction.DefaultClasspathFixProcessor"/>
1775
                <overrides id="org.eclipse.jdt.junit.JUnitClasspathFixProcessor"/>
1776
          </classpathFixProcessor>
1777
       </extension>
1763
</plugin>
1778
</plugin>
(-)src/org/eclipse/pde/internal/ui/correction/java/UnresolvedImportFixProcessor.java (+251 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2007 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
10
 *******************************************************************************/
11
package org.eclipse.pde.internal.ui.correction.java;
12
13
import java.util.HashSet;
14
import java.util.Iterator;
15
import java.util.Set;
16
17
import org.eclipse.core.resources.IProject;
18
import org.eclipse.core.runtime.CoreException;
19
import org.eclipse.core.runtime.IProgressMonitor;
20
import org.eclipse.core.runtime.OperationCanceledException;
21
import org.eclipse.core.runtime.Status;
22
import org.eclipse.jdt.core.IJavaProject;
23
import org.eclipse.jdt.ui.ISharedImages;
24
import org.eclipse.jdt.ui.JavaUI;
25
import org.eclipse.jdt.ui.text.java.ClasspathFixProcessor;
26
import org.eclipse.ltk.core.refactoring.Change;
27
import org.eclipse.ltk.core.refactoring.RefactoringStatus;
28
import org.eclipse.osgi.service.resolver.BundleDescription;
29
import org.eclipse.osgi.service.resolver.ExportPackageDescription;
30
import org.eclipse.pde.core.IBaseModel;
31
import org.eclipse.pde.core.plugin.IPluginImport;
32
import org.eclipse.pde.internal.core.PDECore;
33
import org.eclipse.pde.internal.core.WorkspaceModelManager;
34
import org.eclipse.pde.internal.core.ibundle.IBundlePluginModelBase;
35
import org.eclipse.pde.internal.ui.util.ModelModification;
36
import org.eclipse.pde.internal.ui.util.PDEModelUtility;
37
import org.eclipse.swt.graphics.Image;
38
39
/**
40
 * Offers a classpath fix proposal if the broken import statement can be
41
 * fixed by adding a plugin dependency (required bundle or package import).
42
 * @since 3.4
43
 */
44
public class UnresolvedImportFixProcessor extends ClasspathFixProcessor {
45
46
	/* (non-Javadoc)
47
	 * @see org.eclipse.jdt.ui.text.java.ClasspathFixProcessor#getFixImportProposals(org.eclipse.jdt.core.IJavaProject, java.lang.String)
48
	 */
49
	public ClasspathFixProposal[] getFixImportProposals(IJavaProject project, String name) throws CoreException {
50
		// TODO Check if project is of a PDE nature (this might be handled already by extension point)
51
		if (project == null || !WorkspaceModelManager.isPluginProject(project.getProject())){
52
			return null;
53
		}
54
		
55
		int idx= name.lastIndexOf('.');
56
		String packageName= idx != -1 ? name.substring(0, idx) : null;
57
		String typeName= name.substring(idx + 1);
58
		if (typeName.length() == 1 && typeName.charAt(0) == '*') {
59
			typeName= null;
60
		}
61
		
62
		if (packageName != null){
63
			// Get the packages exported by all bundles, see if any can provide the required classes
64
			ExportPackageDescription[] knownPackages = PDECore.getDefault().getModelManager().getState().getState().getExportedPackages();
65
			Set validPackages = new HashSet();
66
			for (int i = 0; i < knownPackages.length; i++) {
67
				// TODO Is there a better way to compare, currently no checking of class name
68
				if (knownPackages[i].getName().equals(packageName)){
69
					validPackages.add(knownPackages[i]);
70
				}
71
			}
72
			
73
			// TODO Do we want to create a proposal for every valid package?  Consider using a wizard to choose?
74
			ClasspathFixProposal[] proposals = new ClasspathFixProposal[validPackages.size()];
75
			int counter = 0;
76
			Iterator validPackagesIter = validPackages.iterator();
77
			while (validPackagesIter.hasNext()) {
78
				ExportPackageDescription currentPackage = (ExportPackageDescription) validPackagesIter.next();
79
				proposals[counter++] = new RequireBundleFixProposal(project,currentPackage);
80
			}
81
			if (proposals.length > 0){
82
				return proposals;
83
			}
84
		}
85
		
86
		// TODO Do we want to allow overridden processors to run? 
87
		return new ClasspathFixProposal[0];
88
	}
89
	
90
	/**
91
	 * Proposal to fix a broken import by adding a required bundle.
92
	 */
93
	static class RequireBundleFixProposal extends ClasspathFixProposal{
94
		
95
		private IProject fProject;
96
		private BundleDescription fBundleDescription;
97
		
98
		/**
99
		 * Constructor
100
		 * @param project The project that needs the new required bundle
101
		 * @param packageDescription the package we want a dependency on
102
		 */
103
		public RequireBundleFixProposal(IJavaProject project, ExportPackageDescription packageDescription) {
104
			fProject = project.getProject();
105
			fBundleDescription = packageDescription.getExporter();
106
		}
107
108
		/* (non-Javadoc)
109
		 * @see org.eclipse.jdt.ui.text.java.ClasspathFixProcessor.ClasspathFixProposal#createChange(org.eclipse.core.runtime.IProgressMonitor)
110
		 */
111
		public Change createChange(IProgressMonitor monitor) throws CoreException {
112
			return new BundleRequirementChange(fProject,fBundleDescription, true);
113
		}
114
115
		/* (non-Javadoc)
116
		 * @see org.eclipse.jdt.ui.text.java.ClasspathFixProcessor.ClasspathFixProposal#getAdditionalProposalInfo()
117
		 */
118
		public String getAdditionalProposalInfo() {
119
			return "Adds a bundle to the required bundles for this project.";
120
		}
121
		
122
		/* (non-Javadoc)
123
		 * @see org.eclipse.jdt.ui.text.java.ClasspathFixProcessor.ClasspathFixProposal#getDisplayString()
124
		 */
125
		public String getDisplayString() {
126
			return "Add '" + fBundleDescription.getName() + "' to required bundles";
127
		}
128
129
		/* (non-Javadoc)
130
		 * @see org.eclipse.jdt.ui.text.java.ClasspathFixProcessor.ClasspathFixProposal#getImage()
131
		 */
132
		public Image getImage() {
133
			return JavaUI.getSharedImages().getImage(ISharedImages.IMG_OBJS_LIBRARY);
134
		}
135
136
		/* (non-Javadoc)
137
		 * @see org.eclipse.jdt.ui.text.java.ClasspathFixProcessor.ClasspathFixProposal#getRelevance()
138
		 */
139
		public int getRelevance() {
140
			return 16;
141
		}
142
	}
143
	
144
	/**
145
	 * Change that actually adds the required bundle dependency.
146
	 */
147
	static class BundleRequirementChange extends Change{	
148
	
149
		private IProject fBaseProject;
150
		private BundleDescription fBundle;
151
		private boolean fIsAdd;
152
		
153
		/**
154
		 * Constructor
155
		 * @param project the project to add the dependency to
156
		 * @param bundleDescription the bundle to add as a dependency
157
		 */
158
		public BundleRequirementChange(IProject project, BundleDescription bundleDescription, boolean isAdd) {
159
			fBaseProject = project;
160
			fBundle = bundleDescription;
161
			fIsAdd= isAdd;
162
		}
163
		
164
		/* (non-Javadoc)
165
		 * @see org.eclipse.ltk.core.refactoring.Change#perform(org.eclipse.core.runtime.IProgressMonitor)
166
		 */
167
		public Change perform(IProgressMonitor pm) throws CoreException {
168
			// TODO if the IBaseModel is a org.eclipse.pde.internal.core.text.plugin.PluginModelBase, the IPluginImport should be a PluginImportNode that will make it work for 3.0 projects also
169
			ModelModification modelMod = new ModelModification(fBaseProject){
170
				protected void modifyModel(IBaseModel model, IProgressMonitor monitor) throws CoreException {
171
					if (model instanceof IBundlePluginModelBase) {
172
						addOrRemoveRequiredBundle(monitor, (IBundlePluginModelBase)model, fBundle);
173
					}
174
				}
175
			};
176
			PDEModelUtility.modifyModel(modelMod, pm);
177
			return new BundleRequirementChange(fBaseProject, fBundle, !fIsAdd);
178
		}
179
	
180
		/* (non-Javadoc)
181
		 * @see org.eclipse.ltk.core.refactoring.Change#isValid(org.eclipse.core.runtime.IProgressMonitor)
182
		 */
183
		public RefactoringStatus isValid(IProgressMonitor pm) throws CoreException,	OperationCanceledException {
184
			return RefactoringStatus.create(Status.OK_STATUS);
185
		}
186
	
187
		/* (non-Javadoc)
188
		 * @see org.eclipse.ltk.core.refactoring.Change#initializeValidationData(org.eclipse.core.runtime.IProgressMonitor)
189
		 */
190
		public void initializeValidationData(IProgressMonitor pm) {
191
		}
192
	
193
		/* (non-Javadoc)
194
		 * @see org.eclipse.ltk.core.refactoring.Change#getName()
195
		 */
196
		public String getName() {
197
			if (fIsAdd) {
198
				return "Add '" + fBundle.getName() + "' to required bundles";
199
			}
200
			return "Remove '" + fBundle.getName() + "' from required bundles";
201
		}
202
	
203
		/* (non-Javadoc)
204
		 * @see org.eclipse.ltk.core.refactoring.Change#getModifiedElement()
205
		 */
206
		public Object getModifiedElement() {
207
			return fBaseProject;
208
		}
209
		
210
		/**
211
		 * Adds the given bundle to the list of required bundles
212
		 * @param monitor
213
		 * @param baseBundle
214
		 * @param addBundle
215
		 * @throws CoreException
216
		 */
217
		private void addOrRemoveRequiredBundle(IProgressMonitor monitor, IBundlePluginModelBase baseBundle, BundleDescription addBundle) throws CoreException {
218
			// TODO Does not check if the bundle already is in the manifest?
219
			IPluginImport pluginImport = baseBundle.createImport();
220
			pluginImport.setId(addBundle.getSymbolicName());
221
			if (fIsAdd) {
222
				baseBundle.getPluginBase().add(pluginImport);
223
			} else {
224
				baseBundle.getPluginBase().remove(pluginImport);
225
			}
226
		}
227
		
228
//		public static void organizeImportPackages(IBundle bundle, boolean removeImports) {
229
//			if (!(bundle instanceof Bundle))
230
//				return;
231
//			ImportPackageHeader header = (ImportPackageHeader)((Bundle)bundle).getManifestHeader(Constants.IMPORT_PACKAGE);
232
//			if (header == null)
233
//				return;
234
//			ImportPackageObject[] importedPackages = header.getPackages();
235
//			Set availablePackages = getAvailableExportedPackages();
236
//			// get Preference
237
//			for (int i = 0; i < importedPackages.length; i++) {
238
//				String pkgName = importedPackages[i].getName();
239
//				if (!availablePackages.contains(pkgName)){
240
//					if (removeImports)
241
//						header.removePackage(importedPackages[i]);
242
//					else {
243
//						importedPackages[i].setOptional(true);
244
//					}
245
//				}
246
//			}
247
//		}
248
		
249
	}
250
	
251
}

Return to bug 88204