diff options
author | Carsten Pfeiffer | 2012-11-26 19:51:17 +0000 |
---|---|---|
committer | Curtis Windatt | 2012-11-26 19:51:17 +0000 |
commit | 84b471a2fabf3bc475d09adc7a80cf9c0ed001fe (patch) | |
tree | c715bfa2234f9c56eb95e9d31471ce6c3683930b | |
parent | 64a8cc628523b1b729a8051c175da12e9c5f7421 (diff) | |
download | eclipse.pde.ui-84b471a2fabf3bc475d09adc7a80cf9c0ed001fe.tar.gz eclipse.pde.ui-84b471a2fabf3bc475d09adc7a80cf9c0ed001fe.tar.xz eclipse.pde.ui-84b471a2fabf3bc475d09adc7a80cf9c0ed001fe.zip |
Bug 381975 - [patch] Improved support for import package/export packagev20121126-195117I20121127-0800
(quickfixes)
2 files changed, 285 insertions, 61 deletions
diff --git a/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/correction/java/FindClassResolutionsOperation.java b/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/correction/java/FindClassResolutionsOperation.java index 20f7e2c602..b0008add0d 100644 --- a/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/correction/java/FindClassResolutionsOperation.java +++ b/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/correction/java/FindClassResolutionsOperation.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2008 IBM Corporation and others. + * Copyright (c) 2008, 2012 IBM Corporation and others. * 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 @@ -10,12 +10,12 @@ *******************************************************************************/ package org.eclipse.pde.internal.ui.correction.java; -import org.eclipse.osgi.service.resolver.ExportPackageDescription; - import java.util.*; import org.eclipse.core.resources.IProject; -import org.eclipse.core.runtime.IProgressMonitor; -import org.eclipse.core.runtime.Platform; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.runtime.*; +import org.eclipse.jdt.core.*; +import org.eclipse.jdt.core.search.*; import org.eclipse.jface.operation.IRunnableWithProgress; import org.eclipse.osgi.service.resolver.*; import org.eclipse.pde.core.plugin.IPluginModelBase; @@ -27,7 +27,6 @@ import org.eclipse.pde.internal.core.PDECore; * When it is run, it will pass any ExportPackageDescriptions which provide the package to the AbstractClassResolutionCollector. * The AbstractClassResolutionCollector is responsible for creating the appropriate resolutions. * - * @since 3.4 */ public class FindClassResolutionsOperation implements IRunnableWithProgress { @@ -39,7 +38,6 @@ public class FindClassResolutionsOperation implements IRunnableWithProgress { * This class is meant to be sub-classed for use with FindClassResolutionsOperation. The subclass is responsible for creating * corresponding proposals with the help of JavaResolutionFactory. * - * @since 3.4 * @see JavaResolutionFactory */ public static abstract class AbstractClassResolutionCollector { @@ -50,13 +48,36 @@ public class FindClassResolutionsOperation implements IRunnableWithProgress { */ abstract public void addResolutionModification(IProject project, ExportPackageDescription desc); + /** + * Adds an export package proposal. Subclasses should implement the actual adding to the collection. + */ + public Object addExportPackageResolutionModification(IPackageFragment aPackage) { + if (aPackage.exists()) { + return JavaResolutionFactory.createExportPackageProposal(aPackage.getResource().getProject(), aPackage, JavaResolutionFactory.TYPE_JAVA_COMPLETION, 100); + } + return null; + } + + /** + * Adds a require bundle proposal. Subclasses should implement the actual adding to the collection. + */ + public Object addRequireBundleModification(IProject project, ExportPackageDescription desc, int relevance) { + return JavaResolutionFactory.createRequireBundleProposal(project, desc, JavaResolutionFactory.TYPE_JAVA_COMPLETION, relevance); + } + + /** + * Adds a search repositories proposal. Subclasses should implement the actual adding to the collection. + */ + public Object addSearchRepositoriesModification(String packageName) { + return JavaResolutionFactory.createSearchRepositoriesProposal(packageName); + } + /* * Optimization for case where users is only interested in Import-Package and therefore can quit after first dependency is found */ public boolean isDone() { return false; } - } /** @@ -85,12 +106,22 @@ public class FindClassResolutionsOperation implements IRunnableWithProgress { typeName = null; } - if (packageName != null && !isImportedPackage(packageName)) { - Set<ExportPackageDescription> validPackages = getValidPackages(packageName); + Set<IPackageFragment> packagesToExport = new HashSet<IPackageFragment>(); + Collection<ExportPackageDescription> validPackages = getValidPackages(typeName, packageName, packagesToExport, monitor); + if (validPackages != null) { + + if (validPackages.isEmpty()) { + for (Iterator<IPackageFragment> it = packagesToExport.iterator(); it.hasNext();) { + IPackageFragment packageFragment = it.next(); + fCollector.addExportPackageResolutionModification(packageFragment); + } + return; + } + Iterator<ExportPackageDescription> validPackagesIter = validPackages.iterator(); Set<ExportPackageDescription> visiblePkgs = null; - - while (validPackagesIter.hasNext() && !fCollector.isDone()) { + boolean allowMultipleFixes = packageName == null; + while (validPackagesIter.hasNext() && (allowMultipleFixes || !fCollector.isDone())) { // since getting visible packages is not very efficient, only do it once and cache result if (visiblePkgs == null) { visiblePkgs = getVisiblePackages(); @@ -103,40 +134,156 @@ public class FindClassResolutionsOperation implements IRunnableWithProgress { // if currentPackage will resolve class and is valid, pass it to collector fCollector.addResolutionModification(fProject, currentPackage); } + + // additionally add require bundle proposals + for (validPackagesIter = validPackages.iterator(); validPackagesIter.hasNext();) { + ExportPackageDescription currentPackage = validPackagesIter.next(); + fCollector.addRequireBundleModification(fProject, currentPackage, 16); + } } } - private boolean isImportedPackage(String packageName) { - IPluginModelBase model = PluginRegistry.findModel(fProject.getProject()); + private Collection<ExportPackageDescription> getValidPackages(String typeName, String packageName, Set<IPackageFragment> packagesToExport, IProgressMonitor monitor) { + SubMonitor subMonitor = SubMonitor.convert(monitor, 3); + + Collection<ExportPackageDescription> validPackages = null; + ImportPackageSpecification[] importPkgs = null; + IPluginModelBase model = PluginRegistry.findModel(fProject); if (model != null && model.getBundleDescription() != null) { - ImportPackageSpecification[] importPkgs = model.getBundleDescription().getImportPackages(); - for (int i = 0; i < importPkgs.length; i++) { - if (importPkgs[i].getName().equals(packageName)) { - return true; + importPkgs = model.getBundleDescription().getImportPackages(); + } + subMonitor.worked(1); + + if (importPkgs != null) { + if (packageName != null) { + if (!isImportedPackage(packageName, importPkgs)) { + validPackages = getValidPackages(packageName); } + subMonitor.worked(1); + } else { + // find possible types in the global packages + validPackages = findValidPackagesContainingSimpleType(typeName, importPkgs, packagesToExport, subMonitor.newChild(1)); } - return false; } - // if no BundleDescription, we return true so we don't create any proposals. This is the safe way out if no BundleDescription is available. - return true; + return validPackages; } - private static Set<ExportPackageDescription> getValidPackages(String pkgName) { + /** + * Finds all exported packages containing the simple type aTypeName. The packages + * will be filtered from the given packages which are already imported, and all + * system packages. + * + * If no exported package is left, packagesToExport will be filled with those + * packages that would have been returned, if they were exported. + * @param aTypeName the simple type to search for + * @param importPkgs the packages which are already imported + * @param packagesToExport return parameter that will be filled with packages to export + * if no valid package to import was found + * @param monitor + * @return the set of packages to import + */ + private Collection<ExportPackageDescription> findValidPackagesContainingSimpleType(String aTypeName, ImportPackageSpecification[] importPkgs, Set<IPackageFragment> packagesToExport, IProgressMonitor monitor) { + SubMonitor subMonitor = SubMonitor.convert(monitor); + + IPluginModelBase[] activeModels = PluginRegistry.getActiveModels(); + Set<IJavaProject> javaProjects = new HashSet<IJavaProject>(activeModels.length * 2); + + for (int i = 0; i < activeModels.length; i++) { + IResource resource = activeModels[i].getUnderlyingResource(); + if (resource != null && resource.isAccessible()) { + IJavaProject javaProject = JavaCore.create(resource.getProject()); + if (javaProject.exists()) { + javaProjects.add(javaProject); + } + } + } + final IJavaProject currentJavaProject = JavaCore.create(fProject); + javaProjects.remove(currentJavaProject); // no need to search in current project itself + + try { + IJavaSearchScope searchScope = SearchEngine.createJavaSearchScope(javaProjects.toArray(new IJavaElement[javaProjects.size()])); + + final Map<String, IPackageFragment> packages = new HashMap<String, IPackageFragment>(); + SearchRequestor requestor = new SearchRequestor() { + + public void acceptSearchMatch(SearchMatch aMatch) throws CoreException { + Object element = aMatch.getElement(); + if (element instanceof IType) { + IType type = (IType) element; + if (!currentJavaProject.equals(type.getJavaProject())) { + IPackageFragment packageFragment = type.getPackageFragment(); + if (packageFragment.exists()) { + packages.put(packageFragment.getElementName(), packageFragment); + } + } + } + } + }; + + SearchPattern typePattern = SearchPattern.createPattern(aTypeName, IJavaSearchConstants.TYPE, IJavaSearchConstants.DECLARATIONS, SearchPattern.R_EXACT_MATCH | SearchPattern.R_CASE_SENSITIVE); + new SearchEngine().search(typePattern, new SearchParticipant[] {SearchEngine.getDefaultSearchParticipant()}, searchScope, requestor, subMonitor.newChild(1)); + + if (!packages.isEmpty()) { + // transform to ExportPackageDescriptions + Map<String, ExportPackageDescription> exportDescriptions = new HashMap<String, ExportPackageDescription>(packages.size()); + + // remove system packages if they happen to be included. Adding a system package won't resolve anything, since package package already comes from JRE + ExportPackageDescription[] systemPackages = PDECore.getDefault().getModelManager().getState().getState().getSystemPackages(); + for (int i = 0; i < systemPackages.length; i++) { + packages.remove(systemPackages[i].getName()); + } + // also remove packages that are already imported + for (int i = 0; i < importPkgs.length; i++) { + packages.remove(importPkgs[i].getName()); + } + + // finally create the list of ExportPackageDescriptions + ExportPackageDescription[] knownPackages = PDECore.getDefault().getModelManager().getState().getState().getExportedPackages(); + for (int i = 0; i < knownPackages.length; i++) { + if (packages.containsKey(knownPackages[i].getName())) { + exportDescriptions.put(knownPackages[i].getName(), knownPackages[i]); + } + } + if (exportDescriptions.isEmpty()) { + // no packages to import found, maybe there are packages to export + packagesToExport.addAll(packages.values()); + } + + return exportDescriptions.values(); + } + + return Collections.emptySet(); + } catch (CoreException ex) { + // ignore, return an empty set + return Collections.emptySet(); + } + } + + private boolean isImportedPackage(String packageName, ImportPackageSpecification[] importPkgs) { + for (int i = 0; i < importPkgs.length; i++) { + if (importPkgs[i].getName().equals(packageName)) { + return true; + } + } + return false; + } + + private static Collection<ExportPackageDescription> getValidPackages(String pkgName) { ExportPackageDescription[] knownPackages = PDECore.getDefault().getModelManager().getState().getState().getExportedPackages(); - Set<ExportPackageDescription> validPackages = new HashSet<ExportPackageDescription>(); + Map<String, ExportPackageDescription> validPackages = new HashMap<String, ExportPackageDescription>(); for (int i = 0; i < knownPackages.length; i++) { if (knownPackages[i].getName().equals(pkgName)) { - validPackages.add(knownPackages[i]); + validPackages.put(knownPackages[i].getName(), knownPackages[i]); } } // remove system packages if they happen to be included. Adding a system package won't resolve anything, since package package already comes from JRE if (!validPackages.isEmpty()) { knownPackages = PDECore.getDefault().getModelManager().getState().getState().getSystemPackages(); for (int i = 0; i < knownPackages.length; i++) { - validPackages.remove(knownPackages[i]); + validPackages.remove(knownPackages[i].getName()); } } - return validPackages; + return validPackages.values(); } private Set<ExportPackageDescription> getVisiblePackages() { diff --git a/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/correction/java/QuickFixProcessor.java b/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/correction/java/QuickFixProcessor.java index 14b226634c..4319e34eb8 100644 --- a/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/correction/java/QuickFixProcessor.java +++ b/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/correction/java/QuickFixProcessor.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2007, 2011 IBM Corporation and others. + * Copyright (c) 2007, 2012 IBM Corporation and others. * 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 @@ -33,13 +33,21 @@ public class QuickFixProcessor implements IQuickFixProcessor { */ public IJavaCompletionProposal[] getCorrections(IInvocationContext context, IProblemLocation[] locations) throws CoreException { ArrayList<Object> results = new ArrayList<Object>(); + + AbstractClassResolutionCollector collector = createCollector(results); + for (int i = 0; i < locations.length; i++) { int id = locations[i].getProblemId(); switch (id) { case IProblem.ForbiddenReference : - handleAccessRestrictionProblem(context, locations[i], results); - case IProblem.ImportNotFound : - handleImportNotFound(context, locations[i], results); + handleAccessRestrictionProblem(context, locations[i], collector); + case IProblem.ImportNotFound : // fall through + case IProblem.UndefinedName : // fall through + case IProblem.UndefinedType : // fall through + case IProblem.UnresolvedVariable : // fall through + case IProblem.MissingTypeInMethod : // fall through + case IProblem.MissingTypeInConstructor : + handleImportNotFound(context, locations[i], collector); } } @@ -49,13 +57,23 @@ public class QuickFixProcessor implements IQuickFixProcessor { /* * Adds IJavaCompletionProposals for a ForbiddenReference marker */ - private void handleAccessRestrictionProblem(IInvocationContext context, IProblemLocation location, Collection<Object> results) { + private void handleAccessRestrictionProblem(IInvocationContext context, IProblemLocation location, AbstractClassResolutionCollector collector) { IBinding referencedElement = null; ASTNode node = location.getCoveredNode(context.getASTRoot()); if (node instanceof Type) { referencedElement = ((Type) node).resolveBinding(); } else if (node instanceof Name) { referencedElement = ((Name) node).resolveBinding(); + } else if (node instanceof MethodInvocation) { + IMethodBinding tempMethod = ((MethodInvocation) node).resolveMethodBinding(); + if (tempMethod != null) { + referencedElement = tempMethod.getDeclaringClass(); + } + } else if (node instanceof FieldAccess) { + IVariableBinding tempVariable = ((FieldAccess) node).resolveFieldBinding(); + if (tempVariable != null) { + referencedElement = tempVariable.getDeclaringClass(); + } } if (referencedElement != null) { // get the project that contains the reference element @@ -78,19 +96,17 @@ public class QuickFixProcessor implements IQuickFixProcessor { if (exportPackages[i].getName().equals(referencedPackage.getElementName())) { packageExported = true; // check to see if access restriction is caused by Import-Package - handleAccessRestrictionByImportPackage(context.getCompilationUnit().getJavaProject().getProject(), exportPackages[i], results); + handleAccessRestrictionByImportPackage(context.getCompilationUnit().getJavaProject().getProject(), exportPackages[i], collector); break; } } // if the package is not exported, add the quickfix if (!packageExported) { - Object proposal = JavaResolutionFactory.createExportPackageProposal(referencedJavaProject.getProject(), referencedPackage, JavaResolutionFactory.TYPE_JAVA_COMPLETION, 100); - if (proposal != null) - results.add(proposal); + collector.addExportPackageResolutionModification(referencedPackage); } } } else { - handleAccessRestrictionByImportPackage(referencedPackage, results); + handleAccessRestrictionByImportPackage(referencedPackage, collector); } } } @@ -99,31 +115,35 @@ public class QuickFixProcessor implements IQuickFixProcessor { /* * Adds IJavaCompletionProposals for a Require-Bundle if user is using an Import-Package from the bundle */ - private void handleAccessRestrictionByImportPackage(IPackageFragment fragment, Collection<Object> results) { + private void handleAccessRestrictionByImportPackage(IPackageFragment fragment, AbstractClassResolutionCollector collector) { HashSet<String> set = new HashSet<String>(); IProject project = fragment.getJavaProject().getProject(); String pkgName = fragment.getElementName(); IPluginModelBase base = PluginRegistry.findModel(project); ExportPackageDescription[] descs = base.getBundleDescription().getResolvedImports(); + ExportPackageDescription foundExportPackage = null; for (int i = 0; i < descs.length; i++) { BundleDescription exporter = descs[i].getExporter(); if (set.add(exporter.getSymbolicName())) { ExportPackageDescription[] exportedPkgs = exporter.getExportPackages(); for (int j = 0; j < exportedPkgs.length; j++) { if (exportedPkgs[j].getName().equals(pkgName)) { - Object proposal = JavaResolutionFactory.createRequireBundleProposal(project, exportedPkgs[j], JavaResolutionFactory.TYPE_JAVA_COMPLETION, 16); - if (proposal != null) - results.add(proposal); + foundExportPackage = exportedPkgs[j]; // any one is fine, so simply remember the last one + collector.addRequireBundleModification(project, exportedPkgs[j], 16); + break; } } } } + if (foundExportPackage != null) { + collector.addResolutionModification(project, foundExportPackage); + } } /* * Adds IJavaCompletionProposal for a Require-Bundle if user is using an Import-Package from the (workspace) bundle */ - private void handleAccessRestrictionByImportPackage(IProject currentProject, ExportPackageDescription desc, Collection<Object> results) { + private void handleAccessRestrictionByImportPackage(IProject currentProject, ExportPackageDescription desc, AbstractClassResolutionCollector collector) { BundleDescription supplier = desc.getSupplier(); if (supplier != null) { String supplierId = supplier.getSymbolicName(); @@ -139,9 +159,22 @@ public class QuickFixProcessor implements IQuickFixProcessor { } } if (!supplierImported) { - Object proposal = JavaResolutionFactory.createRequireBundleProposal(currentProject, desc, JavaResolutionFactory.TYPE_JAVA_COMPLETION, 16); - if (proposal != null) - results.add(proposal); + // add import-package, if possible + boolean proposeImportPackage = true; + + ImportPackageSpecification[] importPackages = bd.getImportPackages(); + for (int i = 0; i < importPackages.length; i++) { + if (desc.getName().equals(importPackages[i].getName())) { + // already imported, try require-bundle + proposeImportPackage = false; + break; + } + } + + if (proposeImportPackage) { + collector.addResolutionModification(currentProject, desc); // relevance should actually be 16... + } + collector.addRequireBundleModification(currentProject, desc, 16); } } } @@ -149,7 +182,7 @@ public class QuickFixProcessor implements IQuickFixProcessor { /* * Adds IJavaCompletionProposals for a ImportNotFound problem */ - private void handleImportNotFound(IInvocationContext context, IProblemLocation problemLocation, final Collection<Object> result) { + private void handleImportNotFound(IInvocationContext context, IProblemLocation problemLocation, final AbstractClassResolutionCollector collector) { CompilationUnit cu = context.getASTRoot(); ASTNode selectedNode = problemLocation.getCoveringNode(cu); if (selectedNode != null) { @@ -157,29 +190,33 @@ public class QuickFixProcessor implements IQuickFixProcessor { String className = null; String packageName = null; if (node == null) { - if (selectedNode instanceof SimpleName) { - ITypeBinding typeBinding = ((SimpleName) selectedNode).resolveTypeBinding(); - className = typeBinding.getBinaryName(); - packageName = typeBinding.getPackage().getName(); + if (selectedNode instanceof Name) { + ITypeBinding typeBinding = ((Name) selectedNode).resolveTypeBinding(); + if (typeBinding != null) { + className = typeBinding.getBinaryName(); + packageName = typeBinding.getPackage().getName(); + } + if (className == null && selectedNode instanceof SimpleName) { // fallback if the type cannot be resolved + className = ((SimpleName) selectedNode).getIdentifier(); + } } } else if (node instanceof ImportDeclaration) { - // Find import declaration which is the problem - className = ((ImportDeclaration) node).getName().getFullyQualifiedName(); - + // Find the full package name, strip off the class name or on demand qualifier '.*'; + packageName = ((ImportDeclaration) node).getName().getFullyQualifiedName(); + if (!((ImportDeclaration) node).isOnDemand()) { + int lastPeriod = packageName.lastIndexOf('.'); // if there is no period assume we are importing a single name package + packageName = packageName.substring(0, lastPeriod >= 0 ? lastPeriod : packageName.length()); + } // always add the search repositories proposal - int lastPeriod = className.lastIndexOf('.'); // if there is no period assume we are importing a single name package - packageName = className.substring(0, lastPeriod >= 0 ? lastPeriod : className.length()); - result.add(JavaResolutionFactory.createSearchRepositoriesProposal(packageName)); + collector.addSearchRepositoriesModification(packageName); } - if (className != null && packageName != null) { + if (className != null) { IProject project = cu.getJavaElement().getJavaProject().getProject(); // only try to find proposals on Plug-in Projects if (!WorkspaceModelManager.isPluginProject(project)) return; - // create a collector that will create IJavaCompletionProposals and load them into 'result' - AbstractClassResolutionCollector collector = createCollector(result); IRunnableWithProgress findOperation = new FindClassResolutionsOperation(project, className, collector); try { findOperation.run(new NullProgressMonitor()); @@ -191,22 +228,57 @@ public class QuickFixProcessor implements IQuickFixProcessor { } /* - * Custom AbstractClassResolutionCollector which will only add one IJavaCompletionProposal for adding an Import-Package entry + * Custom AbstractClassResolutionCollector which will only add one IJavaCompletionProposal for adding an Import-Package or Export-Package entry */ private AbstractClassResolutionCollector createCollector(final Collection<Object> result) { return new AbstractClassResolutionCollector() { + // the list of package names for which an import package resolution has been created + private Set<String> addedImportPackageResolutions = new HashSet<String>(); + boolean isDone = false; public void addResolutionModification(IProject project, ExportPackageDescription desc) { + // guard against multiple import package resolutions for the same package + if (addedImportPackageResolutions.contains(desc.getName())) { + return; + } + Object proposal = JavaResolutionFactory.createImportPackageProposal(project, desc, JavaResolutionFactory.TYPE_JAVA_COMPLETION, 17); if (proposal != null) { + addedImportPackageResolutions.add(desc.getName()); result.add(proposal); isDone = true; } } - // we want to finish after we add the first Import-Package Change + public Object addExportPackageResolutionModification(IPackageFragment aPackage) { + Object proposal = super.addExportPackageResolutionModification(aPackage); + if (proposal != null) { + result.add(proposal); + } + return proposal; + } + + @Override + public Object addRequireBundleModification(IProject project, ExportPackageDescription desc, int relevance) { + Object proposal = super.addRequireBundleModification(project, desc, relevance); + if (proposal != null) { + result.add(proposal); + } + return proposal; + } + + @Override + public Object addSearchRepositoriesModification(String packageName) { + Object proposal = super.addSearchRepositoriesModification(packageName); + if (proposal != null) { + result.add(proposal); + } + return proposal; + } + + // we want to finish after we add the first Import- or Export-Package Change public boolean isDone() { return isDone; } @@ -229,7 +301,12 @@ public class QuickFixProcessor implements IQuickFixProcessor { public boolean hasCorrections(ICompilationUnit unit, int problemId) { switch (problemId) { case IProblem.ForbiddenReference : - case IProblem.ImportNotFound : + case IProblem.UndefinedName : // fall through + case IProblem.ImportNotFound : // fall through + case IProblem.UndefinedType : // fall through + case IProblem.UnresolvedVariable : // fall through + case IProblem.MissingTypeInMethod : // fall through + case IProblem.MissingTypeInConstructor : IJavaElement parent = unit.getParent(); if (parent != null) { IJavaProject project = parent.getJavaProject(); |