blob: 2a5268b5819d2b589cde05874ac5edc98fa32dce [file] [log] [blame]
/**********************************************************************
* This file is part of "Object Teams Development Tooling"-Software
*
* Copyright 2006, 2007 Technical University Berlin, Germany.
*
* 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
*
* Please visit http://www.eclipse.org/objectteams for updates and contact.
*
* Contributors:
* Technical University Berlin - Initial API and implementation
**********************************************************************/
package org.eclipse.objectteams.otdt.internal.ui.text.correction;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.compiler.IProblem;
import org.eclipse.jdt.core.dom.AST;
import org.eclipse.jdt.core.dom.ASTNode;
import org.eclipse.jdt.core.dom.AbstractMethodMappingDeclaration;
import org.eclipse.jdt.core.dom.ArrayType;
import org.eclipse.jdt.core.dom.CallinMappingDeclaration;
import org.eclipse.jdt.core.dom.CalloutMappingDeclaration;
import org.eclipse.jdt.core.dom.CompilationUnit;
import org.eclipse.jdt.core.dom.IMethodBinding;
import org.eclipse.jdt.core.dom.ITypeBinding;
import org.eclipse.jdt.core.dom.MethodDeclaration;
import org.eclipse.jdt.core.dom.MethodInvocation;
import org.eclipse.jdt.core.dom.MethodSpec;
import org.eclipse.jdt.core.dom.Modifier;
import org.eclipse.jdt.core.dom.Name;
import org.eclipse.jdt.core.dom.ParameterizedType;
import org.eclipse.jdt.core.dom.QualifiedName;
import org.eclipse.jdt.core.dom.QualifiedType;
import org.eclipse.jdt.core.dom.RoleTypeDeclaration;
import org.eclipse.jdt.core.dom.SimpleName;
import org.eclipse.jdt.core.dom.SimpleType;
import org.eclipse.jdt.core.dom.SingleVariableDeclaration;
import org.eclipse.jdt.core.dom.Type;
import org.eclipse.jdt.core.dom.TypeDeclaration;
import org.eclipse.jdt.core.dom.VariableDeclarationStatement;
import org.eclipse.jdt.core.dom.rewrite.ASTRewrite;
import org.eclipse.jdt.internal.corext.dom.Bindings;
import org.eclipse.jdt.internal.corext.util.Messages;
import org.eclipse.jdt.internal.ui.JavaPluginImages;
import org.eclipse.jdt.internal.ui.text.correction.ASTResolving;
import org.eclipse.jdt.internal.ui.text.correction.ModifierCorrectionSubProcessor;
import org.eclipse.jdt.internal.ui.text.correction.proposals.ChangeMethodSignatureProposal;
import org.eclipse.jdt.internal.ui.text.correction.proposals.LinkedCorrectionProposal;
import org.eclipse.jdt.ui.text.java.IInvocationContext;
import org.eclipse.jdt.ui.text.java.IJavaCompletionProposal;
import org.eclipse.jdt.ui.text.java.IProblemLocation;
import org.eclipse.jdt.ui.text.java.IQuickFixProcessor;
import org.eclipse.jdt.ui.text.java.correction.ASTRewriteCorrectionProposal;
import org.eclipse.jdt.ui.text.java.correction.ICommandAccess;
import org.eclipse.objectteams.otdt.internal.ui.assist.OTQuickFixes;
import org.eclipse.swt.graphics.Image;
/**
* Processor for OT/J-specific quickfixes, which mostly delegates to specific sub-processors:
* - ChangeModifierProposalSubProcessor
* - PrecedenceProposalSubProcessor
*
* Some structures borrow ideas from org.eclipse.jdt.internal.ui.text.corrections.QuickFixProcessor
*
* @author stephan
*/
@SuppressWarnings("restriction")
public class QuickFixProcessor implements IQuickFixProcessor {
public boolean hasCorrections(ICompilationUnit unit, int problemId) {
switch (problemId) {
// import:
case IProblem.RegularlyImportedBaseclass:
case IProblem.QualifiedReferenceToBaseclass:
// roles:
case IProblem.MissingTeamForRoleWithMembers:
case IProblem.IllegalModifierForRole:
case IProblem.ReducingRoleVisibility:
case IProblem.AbstractRelevantRole:
case IProblem.AbstractPotentiallyRelevantRole:
case IProblem.MissingAnchorForRoleType:
case IProblem.MissingOverrideAnnotationForRole:
// general method mappings:
case IProblem.DifferentParamInCallinMethodSpec:
case IProblem.UnresolvedCallinMethodSpec:
case IProblem.UnresolvedCalloutMethodSpec:
case IProblem.AmbiguousCallinMethodSpec:
case IProblem.AmbiguousCalloutMethodSpec:
// callout:
case IProblem.RegularCalloutOverrides:
case IProblem.AbstractMethodBoundAsOverride:
// callins:
case IProblem.ReplaceMappingToNonCallin:
case IProblem.CallinMethodBoundNonReplace:
case IProblem.RegularOverridesCallin:
case IProblem.CallinOverridesRegular:
case IProblem.CallinIncompatibleStatic:
case IProblem.ReplaceCallinIncompatibleStatic:
case IProblem.CallinReplaceKeyWordNotOptional:
case IProblem.UnknownPrecedence:
case IProblem.CovariantReturnRequiresTypeParameter:
// externalized roles and visibility:
case IProblem.DeprecatedPathSyntax:
case IProblem.AnchorNotFinal:
case IProblem.AnchorPathNotFinal:
case IProblem.ExternalizedCallToNonPublicConstructor:
case IProblem.ExternalizedCallToNonPublicMethod:
case IProblem.NotVisibleRoleMethod:
case IProblem.NotVisibleRoleConstructor:
case IProblem.TSubMethodReducesVisibility:
// inferred callouts:
case IProblem.UsingCalloutToFieldForFieldRead:
case IProblem.UsingCalloutToFieldForAssignment:
case IProblem.UsingInferredCalloutForMessageSend:
case IProblem.AddingInferredCalloutForInherited:
return true;
// javadoc:
case IProblem.JavadocMissingRoleTag:
// new IProblem for same real problem:
case IProblem.UnhandledLiftingFailedException:
return true;
}
return false;
}
public IJavaCompletionProposal[] getCorrections(IInvocationContext context,
IProblemLocation[] locations)
throws CoreException
{
if (locations == null || locations.length == 0) {
return null;
}
HashSet<Integer> handledProblems= new HashSet<Integer>(locations.length);
ArrayList<ICommandAccess> resultingCollections= new ArrayList<ICommandAccess>();
for (int i= 0; i < locations.length; i++) {
IProblemLocation curr= locations[i];
Integer id= new Integer(curr.getProblemId());
if (handledProblems.add(id)) {
process(context, curr, resultingCollections);
}
}
return resultingCollections.toArray(new IJavaCompletionProposal[resultingCollections.size()]);
}
private void process(IInvocationContext context, IProblemLocation problem, Collection<ICommandAccess> proposals) throws CoreException {
int id= problem.getProblemId();
if (id == 0) { // no proposals for none-problem locations
return;
}
ICompilationUnit cu= context.getCompilationUnit();
ASTNode selectedNode= problem.getCoveringNode(context.getASTRoot());
if (selectedNode == null)
return;
ASTNode enclosingType= ASTResolving.findParentType(selectedNode);
TypeDeclaration parentType= null;
try {
if (enclosingType != null)
parentType = (TypeDeclaration)ASTResolving.findParentType(enclosingType.getParent());
} catch (ClassCastException cce) { /* just no success */ }
CallinMappingDeclaration callinMapping;
CalloutMappingDeclaration calloutMapping;
ICommandAccess javaProposal= null;
try {
switch (id) {
// imports:
case IProblem.RegularlyImportedBaseclass:
javaProposal = TypeProposalSubProcessor.getMakeImportBase(selectedNode, cu);
break;
case IProblem.QualifiedReferenceToBaseclass:
javaProposal = TypeProposalSubProcessor.getImportBaseclass(selectedNode, cu);
break;
// team modifiers:
case IProblem.MissingTeamForRoleWithMembers:
if (parentType != null && parentType instanceof RoleTypeDeclaration)
proposals.add(ChangeModifierProposalSubProcessor
.getMakeTypeTeamProposal(cu, (RoleTypeDeclaration) parentType, 5));
break;
case IProblem.AbstractRelevantRole:
case IProblem.AbstractPotentiallyRelevantRole:
if (parentType != null)
proposals.add(ChangeModifierProposalSubProcessor
.getMakeTypeAbstractProposal(cu, parentType, 8));
break;
// role modifiers:
case IProblem.IllegalModifierForRole:
if (enclosingType instanceof RoleTypeDeclaration) {
RoleTypeDeclaration roleTypeDecl = (RoleTypeDeclaration)enclosingType;
proposals.add(ChangeModifierProposalSubProcessor
.getChangeRoleVisibilityProposal(cu, roleTypeDecl, Modifier.PROTECTED));
proposals.add(ChangeModifierProposalSubProcessor
.getChangeRoleVisibilityProposal(cu, roleTypeDecl, Modifier.PUBLIC));
}
break;
case IProblem.ReducingRoleVisibility:
if (enclosingType instanceof RoleTypeDeclaration) {
RoleTypeDeclaration roleTypeDecl = (RoleTypeDeclaration)enclosingType;
ITypeBinding[] tsupers = roleTypeDecl.resolveBinding().getSuperRoles();
if (tsupers == null || tsupers.length == 0)
break;
int inheritedModifiers = tsupers[0].getModifiers() & ChangeModifierProposalSubProcessor.VISIBILITY_MASK;
proposals.add(ChangeModifierProposalSubProcessor
.getChangeRoleVisibilityProposal(cu, roleTypeDecl, inheritedModifiers));
}
break;
case IProblem.MissingOverrideAnnotationForRole:
// use original from ModifierCorrectionSubProcessor with adaptations:
OTQuickFixes.instance().addOverrideAnnotationProposal(context, problem, proposals);
break;
// general method mappings:
case IProblem.DifferentParamInCallinMethodSpec:
case IProblem.UnresolvedCallinMethodSpec:
case IProblem.UnresolvedCalloutMethodSpec:
MappingProposalSubProcessor.addUnresolvedMethodSpecProposals(selectedNode,
(TypeDeclaration)enclosingType,
context,
problem,
proposals);
MappingProposalSubProcessor.getRemoveMethodMappingSignaturesProposal(cu, selectedNode, 10, proposals);
break;
case IProblem.AmbiguousCallinMethodSpec:
case IProblem.AmbiguousCalloutMethodSpec:
MappingProposalSubProcessor.getAddMethodMappingSignaturesProposal(cu, selectedNode, 10, proposals);
break;
// callout related:
case IProblem.RegularCalloutOverrides:
calloutMapping = (CalloutMappingDeclaration)getEnclosingMethodMapping(selectedNode);
if (calloutMapping != null)
proposals.add(ChangeModifierProposalSubProcessor.getChangeCalloutKindProposal(cu, calloutMapping, true/*toOverride*/));
break;
case IProblem.AbstractMethodBoundAsOverride:
calloutMapping = (CalloutMappingDeclaration)getEnclosingMethodMapping(selectedNode);
if (calloutMapping != null)
proposals.add(ChangeModifierProposalSubProcessor.getChangeCalloutKindProposal(cu, calloutMapping, false/*toOverride*/));
break;
// callin related:
case IProblem.ReplaceMappingToNonCallin:
callinMapping = (CallinMappingDeclaration)getEnclosingMethodMapping(selectedNode);
if (callinMapping != null) {
IMethodBinding roleMethod = ((MethodSpec)callinMapping.getRoleMappingElement()).resolveBinding();
ICommandAccess proposal = ChangeModifierProposalSubProcessor
.getChangeMethodModifierProposal(context, null, roleMethod,
Modifier.OT_CALLIN, true);
if (proposal != null) proposals.add(proposal);
proposals.add(ChangeModifierProposalSubProcessor
.getAddOrChangeCallinModifierProposal(cu, callinMapping));
}
break;
case IProblem.CallinMethodBoundNonReplace:
callinMapping = (CallinMappingDeclaration)getEnclosingMethodMapping(selectedNode);
if (callinMapping != null) {
IMethodBinding roleMethod = ((MethodSpec)callinMapping.getRoleMappingElement()).resolveBinding();
ICommandAccess proposal = ChangeModifierProposalSubProcessor
.getChangeMethodModifierProposal(context, null, roleMethod,
Modifier.OT_CALLIN, false);
if (proposal != null) proposals.add(proposal);
proposals.add(ChangeModifierProposalSubProcessor
.getAddOrChangeCallinModifierProposal(cu, callinMapping));
}
break;
case IProblem.RegularOverridesCallin:
if (selectedNode instanceof MethodDeclaration) {
ICommandAccess proposal = ChangeModifierProposalSubProcessor
.getChangeMethodModifierProposal(context, (MethodDeclaration)selectedNode, null,
Modifier.OT_CALLIN, true);
if (proposal != null) proposals.add(proposal);
}
break;
case IProblem.CallinOverridesRegular:
if (selectedNode instanceof MethodDeclaration) {
ICommandAccess proposal = ChangeModifierProposalSubProcessor
.getChangeMethodModifierProposal(context, (MethodDeclaration)selectedNode, null,
Modifier.OT_CALLIN, false);
if (proposal != null) proposals.add(proposal);
}
break;
case IProblem.CallinIncompatibleStatic:
callinMapping = (CallinMappingDeclaration)getEnclosingMethodMapping(selectedNode);
if (callinMapping != null) {
MethodSpec roleMSpec = (MethodSpec)callinMapping.getRoleMappingElement();
ICommandAccess proposal = ChangeModifierProposalSubProcessor
.getChangeMethodModifierProposal(context, null, roleMSpec.resolveBinding(),
Modifier.STATIC, true);
if (proposal != null) proposals.add(proposal);
}
break;
case IProblem.ReplaceCallinIncompatibleStatic:
callinMapping = (CallinMappingDeclaration)getEnclosingMethodMapping(selectedNode);
if (callinMapping != null) {
MethodSpec roleMSpec = (MethodSpec)callinMapping.getRoleMappingElement();
ICommandAccess proposal = ChangeModifierProposalSubProcessor
.getChangeMethodModifierProposal(context, null, roleMSpec.resolveBinding(),
Modifier.STATIC, false);
if (proposal != null) proposals.add(proposal);
}
break;
case IProblem.CallinReplaceKeyWordNotOptional:
callinMapping = (CallinMappingDeclaration)getEnclosingMethodMapping(selectedNode);
if (callinMapping != null) {
proposals.add(ChangeModifierProposalSubProcessor
.getAddOrChangeCallinModifierProposal(cu, callinMapping));
}
break;
case IProblem.UnknownPrecedence:
if (enclosingType != null) {
ICommandAccess proposal;
PrecedenceProposalSubProcessor processor = new PrecedenceProposalSubProcessor(cu, enclosingType);
proposal = processor.getAddBindingPrecedenceProposal((TypeDeclaration)enclosingType, problem.getProblemArguments());
if (proposal != null)
proposals.add(proposal);
if (parentType != null) {
proposal = processor.getAddBindingPrecedenceToTeamProposal(parentType, problem.getProblemArguments());
if (proposal != null)
proposals.add(proposal);
proposal = processor.getAddRolePrecedenceToTeamProposal(parentType, problem.getProblemArguments());
if (proposal != null)
proposals.add(proposal);
}
}
break;
case IProblem.CovariantReturnRequiresTypeParameter:
javaProposal= MappingProposalSubProcessor.addTypeParameterToCallin(cu, selectedNode, (TypeDeclaration)enclosingType);
break;
// externalized roles:
case IProblem.DeprecatedPathSyntax:
javaProposal= getMigratePathSyntaxProposal(cu, selectedNode);
break;
case IProblem.AnchorNotFinal:
case IProblem.AnchorPathNotFinal:
javaProposal= ChangeModifierProposalSubProcessor.changeAnchorToFinalProposal(cu, selectedNode);
break;
case IProblem.ExternalizedCallToNonPublicConstructor:
case IProblem.ExternalizedCallToNonPublicMethod:
// this processor is orig jdt, but it is adapted by OTQuickFixes/QuickFixCoreAdaptor:
try {
OTQuickFixes.publicRequested = true;
ModifierCorrectionSubProcessor.addNonAccessibleReferenceProposal(context, problem, proposals, ModifierCorrectionSubProcessor.TO_VISIBLE, 10);
} finally {
OTQuickFixes.publicRequested = false;
}
break;
case IProblem.NotVisibleRoleMethod:
case IProblem.NotVisibleRoleConstructor:
// this processor is orig jdt, but it is adapted by OTQuickFixes/QuickFixCoreAdaptor:
ModifierCorrectionSubProcessor.addNonAccessibleReferenceProposal(context, problem, proposals, ModifierCorrectionSubProcessor.TO_VISIBLE, 10);
break;
case IProblem.TSubMethodReducesVisibility:
// this processor is orig jdt, adaptations needed?
ModifierCorrectionSubProcessor.addChangeOverriddenModifierProposal(context, problem, proposals, ModifierCorrectionSubProcessor.TO_VISIBLE);
break;
case IProblem.MissingAnchorForRoleType:
if (selectedNode instanceof VariableDeclarationStatement) {
VariableDeclarationStatement variable = (VariableDeclarationStatement) selectedNode;
selectedNode= variable.getType();
if (selectedNode instanceof SimpleType) {
SimpleType typeNode = (SimpleType) selectedNode;
selectedNode= typeNode.getName();
}
}
if (selectedNode instanceof Name) {
Name typeName= (Name) selectedNode;
ITypeBinding roleType= typeName.resolveTypeBinding();
if (roleType == null) break;
ITypeBinding teamType= roleType.getDeclaringClass();
if (teamType == null) break;
proposals.add(TypeProposalSubProcessor.changeTypeToAnchored(cu,
roleType.getQualifiedName(),
typeName,
teamType.getQualifiedName()));
}
break;
// inferred callout:
case IProblem.UsingCalloutToFieldForAssignment:
javaProposal = MappingProposalSubProcessor.getChangeAssignmentToCalloutCallProposal(
cu, (TypeDeclaration) enclosingType, selectedNode);
// add to proposals below
break;
case IProblem.UsingCalloutToFieldForFieldRead:
javaProposal = MappingProposalSubProcessor.getChangeFieldReadToCalloutCallProposal(
cu, (TypeDeclaration) enclosingType, selectedNode);
// add to proposals below
break;
case IProblem.UsingInferredCalloutForMessageSend:
javaProposal= MappingProposalSubProcessor.getMaterializeInferredCalloutSelfCallProposal(
cu, (TypeDeclaration)enclosingType, (MethodInvocation) selectedNode);
// add to proposals below
break;
case IProblem.AddingInferredCalloutForInherited:
javaProposal= MappingProposalSubProcessor.getMaterializeInferredCalloutsInheritedProposal(
cu, (TypeDeclaration)enclosingType, selectedNode);
// add to proposals below
break;
// javadoc:
case IProblem.JavadocMissingRoleTag:
javaProposal= JavadocProposalSubProcessor.addRoleTag(cu, problem.getProblemArguments(), (TypeDeclaration)enclosingType);
break;
// new IProblem for same real problem:
case IProblem.UnhandledLiftingFailedException:
addUncaughtExceptionProposal(context, problem, selectedNode, proposals);
break;
}
} catch (ClassCastException cce) { /* could not find an expected node */ }
if (javaProposal != null)
proposals.add(javaProposal);
}
static AbstractMethodMappingDeclaration getEnclosingMethodMapping(ASTNode current) {
while (current != null) {
switch (current.getNodeType()) {
case ASTNode.CALLIN_MAPPING_DECLARATION:
case ASTNode.CALLOUT_MAPPING_DECLARATION:
return (AbstractMethodMappingDeclaration)current;
case ASTNode.ROLE_TYPE_DECLARATION:
case ASTNode.TYPE_DECLARATION:
case ASTNode.COMPILATION_UNIT:
return null;
}
current = current.getParent();
}
return null;
}
@SuppressWarnings("unchecked")
private ASTRewriteCorrectionProposal getMigratePathSyntaxProposal(ICompilationUnit cu,
ASTNode selectedNode)
{
if (selectedNode instanceof SingleVariableDeclaration)
selectedNode = ((SingleVariableDeclaration)selectedNode).getType();
ASTNode oldType = selectedNode; // saved for replacing be rewriter
AST ast = oldType.getAST();
// elements for the new type:
String prefixPath = null;
SimpleName typeName = null;
int dimensions = 0;
// strip off dims:
if (selectedNode.getNodeType() == ASTNode.ARRAY_TYPE) {
ArrayType type = (ArrayType)selectedNode;
dimensions = type.getDimensions();
oldType = type.getElementType();
}
// strip off simple type possibly wrapping qualified name:
if (oldType.getNodeType() == ASTNode.SIMPLE_TYPE) {
SimpleType type = (SimpleType)oldType;
oldType = type.getName();
}
// what remains should be a qualified something:
if (oldType.getNodeType() == ASTNode.QUALIFIED_NAME) {
QualifiedName name = (QualifiedName)oldType;
prefixPath = name.getQualifier().toString();
typeName = name.getName();
} else if (oldType.getNodeType() == ASTNode.QUALIFIED_TYPE) {
QualifiedType type = (QualifiedType)oldType;
prefixPath = type.getQualifier().toString();
typeName = type.getName();
}
if (prefixPath != null) {// assemble:
if (prefixPath.equals("base")) //$NON-NLS-1$
prefixPath = baseQualifier(selectedNode, typeName)+prefixPath;
// T
Type simpleType = ast.newSimpleType((Name)ASTNode.copySubtree(ast, typeName));
// T<>
ParameterizedType paramType = ast.newParameterizedType(simpleType);
// T<@prefix.path>
paramType.typeArguments().add(ast.newTypeAnchor(ast.newName(prefixPath)));
// T<@prefix.path>[]..
Type newType = (dimensions == 0) ?
paramType :
ast.newArrayType(paramType, dimensions);
ASTRewrite rewrite = ASTRewrite.create(ast);
rewrite.replace(selectedNode, newType, null);
return new ASTRewriteCorrectionProposal(
Messages.format(CorrectionMessages.OTQuickfix_migrateroletypesyntax_description, null),
cu,
rewrite,
17, // TODO(SH): ;-)
JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_CHANGE));
}
return null;
}
private String baseQualifier(ASTNode selectedNode,
SimpleName typeName)
{
// find enclosing role type:
RoleTypeDeclaration enclType = null;
ASTNode current = selectedNode;
while (enclType == null && current != null) {
current = current.getParent();
if (current instanceof RoleTypeDeclaration)
enclType = (RoleTypeDeclaration)current;
}
// find base class containing 'typeName':
RoleTypeDeclaration currentType = enclType;
int depth = 0;
while(currentType != null) {
// find 'typeName' in baseclass:
ITypeBinding baseclass = currentType.getBaseClassType().resolveBinding();
while (baseclass != null) {
for (ITypeBinding member : baseclass.getDeclaredTypes()) {
if (member.getName().equals(typeName.getIdentifier())) {
if (depth > 0)
return currentType.getName()+"."; //$NON-NLS-1$
break; // success, but no need for a qualifier
}
}
// loop up:
baseclass = baseclass.getSuperclass();
}
if (currentType.getParent() instanceof RoleTypeDeclaration)
// loop out:
currentType = (RoleTypeDeclaration)currentType.getParent();
else
break; // no success, try anyway
depth++;
}
return ""; //$NON-NLS-1$
}
private void addUncaughtExceptionProposal(IInvocationContext context, IProblemLocation problem, ASTNode selectedNode, Collection<ICommandAccess> proposals)
{
// essentially the trailing block of
// org.eclipse.jdt.internal.ui.text.correction.LocalCorrectionsSubProcessor.addUncaughtExceptionProposals()
while (selectedNode != null && !(selectedNode instanceof MethodDeclaration)) {
selectedNode= selectedNode.getParent();
}
if (selectedNode == null) {
return;
}
MethodDeclaration methodDecl= (MethodDeclaration) selectedNode;
ICompilationUnit cu= context.getCompilationUnit();
CompilationUnit astRoot= context.getASTRoot();
IMethodBinding binding= methodDecl.resolveBinding();
boolean isApplicable= (binding != null);
if (isApplicable) {
IMethodBinding overriddenMethod= Bindings.findOverriddenMethod(binding, true);
if (overriddenMethod != null ) {
isApplicable= overriddenMethod.getDeclaringClass().isFromSource();
}
}
if (isApplicable) {
ITypeBinding uncaughtException = astRoot.getAST().resolveWellKnownType("org.objectteams.LiftingFailedException"); //$NON-NLS-1$
ChangeMethodSignatureProposal.ChangeDescription[] desc = {new ChangeMethodSignatureProposal.InsertDescription(uncaughtException, "")}; //$NON-NLS-1$
String label= org.eclipse.jdt.internal.ui.text.correction.CorrectionMessages.LocalCorrectionsSubProcessor_addthrows_description;
Image image= JavaPluginImages.get(JavaPluginImages.IMG_OBJS_EXCEPTION);
ChangeMethodSignatureProposal proposal= new ChangeMethodSignatureProposal(label, cu, astRoot, binding, null, desc, 8, image);
addExceptionTypeLinkProposals(proposal, uncaughtException, proposal.getExceptionTypeGroupId(1));
proposal.setCommandId("org.eclipse.objectteams.otdt.jdt.ui.correction.addThrowsDecl"); //$NON-NLS-1$
proposals.add(proposal);
}
}
private static void addExceptionTypeLinkProposals(LinkedCorrectionProposal proposal, ITypeBinding exc, String key) {
// all super classes except Object
while (exc != null && !"java.lang.Object".equals(exc.getQualifiedName())) { //$NON-NLS-1$
proposal.addLinkedPositionProposal(key, exc);
exc= exc.getSuperclass();
}
}
}