EMMA Coverage Report (generated Thu Nov 26 15:54:18 CST 2009)
[all classes][org.eclipse.pde.api.tools.internal.builder]

COVERAGE SUMMARY FOR SOURCE FILE [IllegalExtendsProblemDetector.java]

nameclass, %method, %block, %line, %
IllegalExtendsProblemDetector.java100% (2/2)92%  (12/13)87%  (442/509)87%  (118/135)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class IllegalExtendsProblemDetector100% (1/1)90%  (9/10)85%  (341/399)87%  (90/103)
getQualifiedMessageArgs (IReference): String [] 0%   (0/1)0%   (0/18)0%   (0/4)
getMessageArgs (IReference): String [] 100% (1/1)79%  (72/91)83%  (19/23)
getSourceRange (IType, IDocument, IReference): Position 100% (1/1)83%  (86/103)88%  (22/25)
quickLookup (IType, IDocument, IReference, int): IMethod 100% (1/1)86%  (18/21)86%  (6/7)
getEnclosingMethod (IType, IReference, IDocument): IMethod 100% (1/1)99%  (138/139)97%  (33/34)
IllegalExtendsProblemDetector (): void 100% (1/1)100% (3/3)100% (1/1)
getProblemFlags (IReference): int 100% (1/1)100% (18/18)100% (6/6)
getProblemKind (): int 100% (1/1)100% (2/2)100% (1/1)
getReferenceKinds (): int 100% (1/1)100% (2/2)100% (1/1)
getSeverityKey (): String 100% (1/1)100% (2/2)100% (1/1)
     
class IllegalExtendsProblemDetector$MethodFinder100% (1/1)100% (3/3)92%  (101/110)88%  (28/32)
visit (AnonymousClassDeclaration): boolean 100% (1/1)80%  (32/40)75%  (9/12)
visit (TypeDeclaration): boolean 100% (1/1)98%  (48/49)92%  (12/13)
IllegalExtendsProblemDetector$MethodFinder (IllegalExtendsProblemDetector, Ap... 100% (1/1)100% (21/21)100% (7/7)

1/*******************************************************************************
2 * Copyright (c) 2008, 2009 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 *******************************************************************************/
11package org.eclipse.pde.api.tools.internal.builder;
12 
13import org.eclipse.core.runtime.CoreException;
14import org.eclipse.jdt.core.ICompilationUnit;
15import org.eclipse.jdt.core.IJavaElement;
16import org.eclipse.jdt.core.IMethod;
17import org.eclipse.jdt.core.ISourceRange;
18import org.eclipse.jdt.core.IType;
19import org.eclipse.jdt.core.JavaModelException;
20import org.eclipse.jdt.core.Signature;
21import org.eclipse.jdt.core.dom.AST;
22import org.eclipse.jdt.core.dom.ASTNode;
23import org.eclipse.jdt.core.dom.ASTParser;
24import org.eclipse.jdt.core.dom.ASTVisitor;
25import org.eclipse.jdt.core.dom.AnonymousClassDeclaration;
26import org.eclipse.jdt.core.dom.ITypeBinding;
27import org.eclipse.jdt.core.dom.TypeDeclaration;
28import org.eclipse.jface.text.BadLocationException;
29import org.eclipse.jface.text.IDocument;
30import org.eclipse.jface.text.Position;
31import org.eclipse.pde.api.tools.internal.model.ApiType;
32import org.eclipse.pde.api.tools.internal.provisional.builder.IReference;
33import org.eclipse.pde.api.tools.internal.provisional.model.IApiMethod;
34import org.eclipse.pde.api.tools.internal.provisional.model.IApiType;
35import org.eclipse.pde.api.tools.internal.provisional.problems.IApiProblem;
36import org.eclipse.pde.api.tools.internal.provisional.problems.IApiProblemTypes;
37import org.eclipse.pde.api.tools.internal.util.Signatures;
38 
39/**
40 * Detects when a type illegally extends another type.
41 * 
42 * @since 1.1
43 */
44public class IllegalExtendsProblemDetector extends AbstractIllegalTypeReference {
45        
46        /**
47         * Class used to look up the name of the enclosing method for an {@link IApiType} when we do not have any 
48         * enclosing method infos (pre Java 1.5 class files 
49         */
50        class MethodFinder extends ASTVisitor {
51                IMethod method = null;
52                private IType jtype = null;
53                private ApiType type = null;
54                
55                public MethodFinder(ApiType type, IType jtype) {
56                        this.type = type;
57                        this.jtype = jtype;
58                }
59                public boolean visit(AnonymousClassDeclaration node) {
60                        if(method == null) {
61                                ITypeBinding binding = node.resolveBinding();
62                                String binaryName = binding.getBinaryName();
63                                if(type.getName().endsWith(binaryName)) {
64                                        try {
65                                                IJavaElement element = jtype.getCompilationUnit().getElementAt(node.getStartPosition());
66                                                if(element != null) {
67                                                        IJavaElement ancestor = element.getAncestor(IJavaElement.METHOD);
68                                                        if(ancestor != null) {
69                                                                method = (IMethod) ancestor;
70                                                        }
71                                                }
72                                        }
73                                        catch(JavaModelException jme) {}
74                                        return false;
75                                }
76                        }
77                        return true;
78                }
79                public boolean visit(TypeDeclaration node) {
80                        if(method == null && node.isLocalTypeDeclaration()) {
81                                ITypeBinding binding = node.resolveBinding();
82                                String binaryName = binding.getBinaryName();
83                                if(type.getName().endsWith(binaryName)) {
84                                        try {
85                                                IJavaElement element = jtype.getCompilationUnit().getElementAt(node.getStartPosition());
86                                                if(element.getElementType() == IJavaElement.TYPE) {
87                                                        IType ltype = (IType) element;
88                                                        IJavaElement parent = ltype.getParent();
89                                                        if(parent.getElementType() == IJavaElement.METHOD) {
90                                                                method = (IMethod) parent;
91                                                        }
92                                                }
93                                        }
94                                        catch(JavaModelException jme) {}
95                                        return false;
96                                }
97                        }
98                        return true;
99                }
100        };
101        
102        /* (non-Javadoc)
103         * @see org.eclipse.pde.api.tools.internal.provisional.search.IApiProblemDetector#getReferenceKinds()
104         */
105        public int getReferenceKinds() {
106                return IReference.REF_EXTENDS;
107        }
108 
109        /* (non-Javadoc)
110         * @see org.eclipse.pde.api.tools.internal.search.AbstractIllegalTypeReference#getProblemKind()
111         */
112        protected int getProblemKind() {
113                return IApiProblem.ILLEGAL_EXTEND;
114        }
115 
116        /* (non-Javadoc)
117         * @see org.eclipse.pde.api.tools.internal.builder.AbstractIllegalTypeReference#getProblemFlags(org.eclipse.pde.api.tools.internal.provisional.builder.IReference)
118         */
119        protected int getProblemFlags(IReference reference) {
120                IApiType type = (IApiType) reference.getMember();
121                if(type.isLocal()) {
122                        return IApiProblem.LOCAL_TYPE;
123                }
124                if(type.isAnonymous()) {
125                        return IApiProblem.ANONYMOUS_TYPE;
126                }
127                return super.getProblemFlags(reference);
128        }
129        
130        /* (non-Javadoc)
131         * @see org.eclipse.pde.api.tools.internal.search.AbstractIllegalTypeReference#getSeverityKey()
132         */
133        protected String getSeverityKey() {
134                return IApiProblemTypes.ILLEGAL_EXTEND;
135        }
136        
137        /* (non-Javadoc)
138         * @see org.eclipse.pde.api.tools.internal.builder.AbstractIllegalTypeReference#getMessageArgs(org.eclipse.pde.api.tools.internal.provisional.builder.IReference)
139         */
140        protected String[] getMessageArgs(IReference reference) throws CoreException {
141                ApiType ltype = (ApiType) reference.getMember();
142                String simpleTypeName = getSimpleTypeName(reference.getResolvedReference());
143                if(ltype.isAnonymous()) {
144                        IApiType etype = ltype.getEnclosingType();
145                        String signature = Signatures.getQualifiedTypeSignature(etype);
146                        IApiMethod method = ltype.getEnclosingMethod();
147                        if(method != null) {
148                                signature = Signatures.getQualifiedMethodSignature(method);
149                        }
150                        return new String[] {signature, simpleTypeName};
151                }
152                if(ltype.isLocal()) {
153                        //local types are always defined in methods, include enclosing method infos in message
154                        IApiType etype = ltype.getEnclosingType(); 
155                        IApiMethod method = ltype.getEnclosingMethod();
156                        if(method != null) {
157                                String methodsig = Signatures.getQualifiedMethodSignature(method);
158                                return new String[] {
159                                                Signatures.getAnonymousTypeName(ltype.getName()),
160                                                methodsig,
161                                                simpleTypeName
162                                };
163                        }
164                        else {
165                                return new String[] {
166                                                Signatures.getAnonymousTypeName(ltype.getName()), 
167                                                getSimpleTypeName(etype), 
168                                                simpleTypeName};
169                        }
170                }
171                return super.getMessageArgs(reference);
172        }
173        
174        /* (non-Javadoc)
175         * @see org.eclipse.pde.api.tools.internal.builder.AbstractIllegalTypeReference#getQualifiedMessageArgs(org.eclipse.pde.api.tools.internal.provisional.builder.IReference)
176         */
177        protected String[] getQualifiedMessageArgs(IReference reference) throws CoreException {
178                ApiType ltype = (ApiType) reference.getMember();
179                if(ltype.isLocal() || ltype.isAnonymous()) {
180                        return this.getMessageArgs(reference);
181                }
182                return super.getQualifiedMessageArgs(reference);
183        }
184        
185        /* (non-Javadoc)
186         * @see org.eclipse.pde.api.tools.internal.builder.AbstractIllegalTypeReference#getSourceRange(org.eclipse.jdt.core.IType, org.eclipse.jface.text.IDocument, org.eclipse.pde.api.tools.internal.provisional.builder.IReference)
187         */
188        protected Position getSourceRange(IType type, IDocument doc, IReference reference) throws CoreException, BadLocationException {
189                ApiType ltype = (ApiType) reference.getMember();
190                IMethod method = null;
191                if(ltype.isAnonymous()) {
192                        // has a side-effect on reference.getMember().setEnclosingMethodInfo(..)
193                        getEnclosingMethod(type, reference, doc);
194                        if(reference.getLineNumber() < 0) {
195                                return defaultSourcePosition(type, reference);
196                        }
197                        String name = getSimpleTypeName(reference.getResolvedReference());
198                        Position pos = getMethodNameRange(true, name, doc, reference);
199                        if(pos == null) {
200                                return defaultSourcePosition(type, reference);
201                        }
202                        return pos;
203                }
204                if(ltype.isLocal()) {
205                        String name = ltype.getSimpleName();
206                        ICompilationUnit cunit = type.getCompilationUnit();
207                        if(cunit.isWorkingCopy()) {
208                                cunit.reconcile(AST.JLS3, false, null, null);
209                        }
210                        IType localtype = type;
211                        method = getEnclosingMethod(type, reference, doc);
212                        if(method != null) {
213                                localtype = method.getType(name, 1);
214                        }
215                        if(localtype.exists()) {
216                                ISourceRange range = localtype.getNameRange();
217                                return new Position(range.getOffset(), range.getLength());
218                        }
219                        return defaultSourcePosition(type, reference);
220                }
221                return super.getSourceRange(type, doc, reference);
222        }
223        /**
224         * Returns the enclosing {@link IMethod} for the given type or <code>null</code>
225         * if it cannot be computed
226         * @param type
227         * @param jtype
228         * @param reference
229         * @param document
230         * @return the {@link IMethod} enclosing the given type or <code>null</code>
231         * @throws CoreException
232         */
233        private IMethod getEnclosingMethod(final IType jtype, IReference reference, IDocument document) throws CoreException { 
234                ApiType type = (ApiType) reference.getMember();
235                IApiMethod apimethod = type.getEnclosingMethod();
236                if(apimethod != null) {
237                        String signature = Signatures.processMethodSignature(apimethod);
238                        String methodname = Signatures.getMethodName(apimethod);
239                        IMethod method = jtype.getMethod(methodname, Signature.getParameterTypes(signature));
240                        if(method.exists()) {
241                                return method;
242                        }
243                }
244                else {
245                        //try to look it up
246                        IMethod method = null;
247                        if(reference.getLineNumber() > -1) {
248                                try {
249                                        int offset = document.getLineOffset(reference.getLineNumber());
250                                        method = quickLookup(jtype, document, reference, offset);
251                                }
252                                catch(BadLocationException ble) {}
253                        }
254                        if(method == null) {
255                                //look it up the hard way
256                                ISourceRange range = jtype.getCompilationUnit().getSourceRange();
257                                ASTParser parser = ASTParser.newParser(AST.JLS3);
258                                parser.setSource(jtype.getCompilationUnit());
259                                parser.setSourceRange(range.getOffset(), range.getLength());
260                                parser.setResolveBindings(true);
261                                ASTNode ptype = parser.createAST(null);
262                                MethodFinder finder = new MethodFinder(type, jtype);
263                                ptype.accept(finder);
264                                method = finder.method;
265                        }
266                        if(method != null && method.exists()) {
267                                ApiType etype = (ApiType) type.getEnclosingType();
268                                IApiMethod[] methods = etype.getMethods();
269                                String msig = null;
270                                for (int i = 0; i < methods.length; i++) {
271                                        msig = methods[i].getSignature();
272                                        if(Signatures.getMethodName(methods[i]).equals(method.getElementName()) &&
273                                                        Signatures.matchesSignatures(msig.replace('/', '.'), method.getSignature())) {
274                                                type.setEnclosingMethodInfo(methods[i].getName(), msig);
275                                        }
276                                }
277                                return method;
278                        }
279                }
280                return null;
281        }
282        private IMethod quickLookup(final IType jtype, IDocument document, IReference reference, int offset) throws JavaModelException {
283                if(offset > -1) {
284                        IJavaElement element = jtype.getCompilationUnit().getElementAt(offset);
285                        if(element != null) {
286                                IJavaElement ancestor = element.getAncestor(IJavaElement.METHOD);
287                                if (ancestor != null) {
288                                        return (IMethod) ancestor;
289                                }
290                        }
291                }
292                return null;
293        }
294}

[all classes][org.eclipse.pde.api.tools.internal.builder]
EMMA 2.0.5312 EclEmma Fix 1 (C) Vladimir Roubtsov