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 [LeakExtendsProblemDetector.java]

nameclass, %method, %block, %line, %
LeakExtendsProblemDetector.java100% (1/1)100% (9/9)88%  (231/262)87%  (62.9/72)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class LeakExtendsProblemDetector100% (1/1)100% (9/9)88%  (231/262)87%  (62.9/72)
gatherAPISuperTypes (List, IApiType): void 100% (1/1)60%  (28/47)72%  (7.9/11)
isProblem (IReference): boolean 100% (1/1)91%  (115/127)85%  (33/39)
LeakExtendsProblemDetector (Set): void 100% (1/1)100% (4/4)100% (2/2)
gatherVisibleMethods (IApiType, Set, int): void 100% (1/1)100% (37/37)100% (6/6)
getProblemFlags (IReference): 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)
hasVisibleField (IApiType, int): boolean 100% (1/1)100% (24/24)100% (6/6)
isAPIType (IApiType): boolean 100% (1/1)100% (17/17)100% (5/5)

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 java.util.HashSet;
14import java.util.Iterator;
15import java.util.LinkedList;
16import java.util.List;
17import java.util.Set;
18 
19import org.eclipse.core.runtime.CoreException;
20import org.eclipse.jdt.core.Flags;
21import org.eclipse.pde.api.tools.internal.model.MethodKey;
22import org.eclipse.pde.api.tools.internal.provisional.ApiPlugin;
23import org.eclipse.pde.api.tools.internal.provisional.IApiAnnotations;
24import org.eclipse.pde.api.tools.internal.provisional.IApiDescription;
25import org.eclipse.pde.api.tools.internal.provisional.RestrictionModifiers;
26import org.eclipse.pde.api.tools.internal.provisional.VisibilityModifiers;
27import org.eclipse.pde.api.tools.internal.provisional.builder.IReference;
28import org.eclipse.pde.api.tools.internal.provisional.model.IApiComponent;
29import org.eclipse.pde.api.tools.internal.provisional.model.IApiField;
30import org.eclipse.pde.api.tools.internal.provisional.model.IApiMethod;
31import org.eclipse.pde.api.tools.internal.provisional.model.IApiType;
32import org.eclipse.pde.api.tools.internal.provisional.problems.IApiProblem;
33import org.eclipse.pde.api.tools.internal.provisional.problems.IApiProblemTypes;
34 
35/**
36 * Detects leaked super types.
37 * 
38 * @since 1.1
39 */
40public class LeakExtendsProblemDetector extends AbstractTypeLeakDetector {
41 
42        /**
43         * @param nonApiPackageNames
44         */
45        public LeakExtendsProblemDetector(Set nonApiPackageNames) {
46                super(nonApiPackageNames);
47        }
48 
49        /* (non-Javadoc)
50         * @see org.eclipse.pde.api.tools.internal.provisional.search.IApiProblemDetector#getReferenceKinds()
51         */
52        public int getReferenceKinds() {
53                return IReference.REF_EXTENDS;
54        }
55 
56        /* (non-Javadoc)
57         * @see org.eclipse.pde.api.tools.internal.search.AbstractProblemDetector#getSeverityKey()
58         */
59        protected String getSeverityKey() {
60                return IApiProblemTypes.LEAK_EXTEND;
61        }
62        
63        /* (non-Javadoc)
64         * @see org.eclipse.pde.api.tools.internal.search.AbstractProblemDetector#getProblemFlags(org.eclipse.pde.api.tools.internal.provisional.model.IReference)
65         */
66        protected int getProblemFlags(IReference reference) {
67                return IApiProblem.LEAK_EXTENDS;
68        }
69        
70        /* (non-Javadoc)
71         * @see org.eclipse.pde.api.tools.internal.search.AbstractTypeLeakDetector#isProblem(org.eclipse.pde.api.tools.internal.provisional.model.IReference)
72         */
73        public boolean isProblem(IReference reference) {
74                if (super.isProblem(reference)) {
75                        // check the use restrictions on the API type (can be extended or not)
76                        IApiType type = (IApiType) reference.getMember();
77                        IApiComponent component = type.getApiComponent();
78                        try {
79                                if (type.isClass()) {
80                                        int modifiers = 0;
81                                        IApiAnnotations annotations = component.getApiDescription().resolveAnnotations(type.getHandle());
82                                        if (annotations != null) {
83                                                // if annotations are null, the reference should not have been retained
84                                                // as it indicates a reference from a top level non public type
85                                                if (RestrictionModifiers.isExtendRestriction(annotations.getRestrictions())) {
86                                                        // The no extend restriction means only public members can be seen
87                                                        modifiers = Flags.AccPublic;
88                                                } else {
89                                                        if (Flags.isFinal(type.getModifiers())) {
90                                                                // if final then only public members can be seen
91                                                                modifiers = Flags.AccPublic;
92                                                        } else {
93                                                                // public and protected members can be seen
94                                                                modifiers = Flags.AccPublic | Flags.AccProtected;
95                                                        }
96                                                }
97                                                IApiType nonApiSuper = type.getSuperclass();
98                                                // collect all visible methods in non-API types
99                                                Set methods = new HashSet();
100                                                while (!isAPIType(nonApiSuper)) {
101                                                        if (hasVisibleField(nonApiSuper, modifiers)) {
102                                                                // a visible field in a non-API type is a definite leak
103                                                                return true;
104                                                        }
105                                                        gatherVisibleMethods(nonApiSuper, methods, modifiers);
106                                                        nonApiSuper = nonApiSuper.getSuperclass();
107                                                }
108                                                if (methods.size() > 0) {
109                                                        // check if the visible members are part of an API interface/class
110                                                        List apiTypes = new LinkedList();
111                                                        apiTypes.add(type);
112                                                        gatherAPISuperTypes(apiTypes, type);
113                                                        Iterator iterator2 = apiTypes.iterator();
114                                                        while (iterator2.hasNext()) {
115                                                                IApiType t2 = (IApiType) iterator2.next();
116                                                                Set apiMembers = new HashSet();
117                                                                gatherVisibleMethods(t2, apiMembers, modifiers);
118                                                                methods.removeAll(apiMembers);
119                                                                if (methods.size() == 0) {
120                                                                        // there are no visible methods left that are not part of an API type/interface
121                                                                        return false;
122                                                                }        
123                                                        }
124                                                        if (methods.size() > 0) {
125                                                                // there are visible members that are not part of an API type/interface
126                                                                return true;
127                                                        }
128                                                }
129                                        }
130                                } else {
131                                        // don't process interfaces, enums, annotations
132                                        return true;
133                                }
134                        } catch (CoreException ce) {
135                                if(DEBUG) {
136                                        ApiPlugin.log(ce);
137                                }
138                                return true;
139                        }
140                }
141                return false;
142        }
143 
144        /**
145         * Adds all visible methods to the given set in the specified type.
146         * 
147         * @param type type to analyze
148         * @param members set to add methods to
149         * @param modifiers visibilities to consider
150         */
151        private void gatherVisibleMethods(IApiType type, Set members, int modifiers) {
152                IApiMethod[] methods = type.getMethods();
153                for (int i = 0; i < methods.length; i++) {
154                        IApiMethod method = methods[i];
155                        if ((method.getModifiers() & modifiers) > 0 && !method.isConstructor() && !method.isSynthetic()) {
156                                members.add(new MethodKey(method.getName(), method.getSignature()));
157                        }
158                }
159        }
160        
161        /**
162         * Returns whether the given type has any visible fields base on the given
163         * visibility flags to consider. A field is visible signals a definite leak.
164         * 
165         * @param type type to analyze
166         * @param modifiers visibilities to consider
167         * @return whether there are any visible fields
168         */
169        private boolean hasVisibleField(IApiType type, int modifiers) {
170                IApiField[] fields = type.getFields();
171                for (int i = 0; i < fields.length; i++) {
172                        IApiField field = fields[i];
173                        if ((field.getModifiers() & modifiers) > 0) {
174                                return true;
175                        }
176                }
177                return false;
178        }
179        
180        /**
181         * Adds all API super types of the given type to the given list in
182         * top down order.
183         * 
184         * @param superTypes list to add to
185         * @param type type being processed
186         */
187        private void gatherAPISuperTypes(List superTypes, IApiType type) throws CoreException {
188                if (type != null) {
189                        if (isAPIType(type)) {
190                                superTypes.add(0, type);
191                        }
192                        gatherAPISuperTypes(superTypes, type.getSuperclass());
193                        IApiType[] interfaces = type.getSuperInterfaces();
194                        if (interfaces != null) {
195                                for (int i = 0; i < interfaces.length; i++) {
196                                        if (isAPIType(interfaces[i])) {
197                                                superTypes.add(interfaces[i]);
198                                                gatherAPISuperTypes(superTypes, interfaces[i]);
199                                        }
200                                }
201                        }
202                }
203        }        
204 
205        /**
206         * Returns whether the given type has API visibility.
207         * 
208         * @param type type
209         * @return whether the given type has API visibility
210         */
211        private boolean isAPIType(IApiType type) throws CoreException {
212                IApiDescription description = type.getApiComponent().getApiDescription();
213                IApiAnnotations annotations = description.resolveAnnotations(type.getHandle());
214                if (annotations == null) {
215                        // top level non-public top can have no annotations - they are not API
216                        return false;
217                }
218                return VisibilityModifiers.isAPI(annotations.getVisibility());
219        }        
220        
221}

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