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

nameclass, %method, %block, %line, %
ReferenceAnalyzer.java100% (3/3)93%  (14/15)81%  (466/577)84%  (112.6/134)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class ReferenceAnalyzer100% (1/1)89%  (8/9)76%  (332/435)81%  (79.6/98)
setDebug (boolean): void 0%   (0/1)0%   (0/9)0%   (0/2)
extractReferences (IApiTypeContainer, IProgressMonitor): void 100% (1/1)56%  (40/71)73%  (11/15)
analyze (IApiTypeContainer, IApiProblemDetector [], IProgressMonitor): IApiPr... 100% (1/1)70%  (89/128)78%  (22.7/29)
buildProblemDetectors (IApiComponent, IProgressMonitor): IApiProblemDetector [] 100% (1/1)75%  (73/97)73%  (16.9/23)
<static initializer> 100% (1/1)100% (12/12)100% (5/5)
ReferenceAnalyzer (): void 100% (1/1)100% (11/11)100% (3/3)
analyze (IApiComponent, IApiTypeContainer, IProgressMonitor): IApiProblem [] 100% (1/1)100% (11/11)100% (2/2)
getLog2 (int): int 100% (1/1)100% (12/12)100% (3/3)
indexProblemDetectors (IApiProblemDetector []): void 100% (1/1)100% (84/84)100% (17/17)
     
class ReferenceAnalyzer$Visitor100% (1/1)100% (4/4)93%  (108/116)90%  (28/31)
visit (String, IApiTypeRoot): void 100% (1/1)91%  (78/86)87%  (20/23)
ReferenceAnalyzer$Visitor (ReferenceAnalyzer, IProgressMonitor): void 100% (1/1)100% (12/12)100% (4/4)
endVisitPackage (String): void 100% (1/1)100% (5/5)100% (2/2)
visitPackage (String): boolean 100% (1/1)100% (13/13)100% (2/2)
     
class ReferenceAnalyzer$1100% (1/1)100% (2/2)100% (26/26)100% (6/6)
ReferenceAnalyzer$1 (ReferenceAnalyzer, ProblemDetectorBuilder): void 100% (1/1)100% (9/9)100% (2/2)
visitElement (IElementDescriptor, IApiAnnotations): boolean 100% (1/1)100% (17/17)100% (4/4)

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.Iterator;
14import java.util.LinkedList;
15import java.util.List;
16 
17import org.eclipse.core.runtime.CoreException;
18import org.eclipse.core.runtime.IProgressMonitor;
19import org.eclipse.core.runtime.MultiStatus;
20import org.eclipse.core.runtime.SubMonitor;
21import org.eclipse.pde.api.tools.internal.provisional.ApiDescriptionVisitor;
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.VisibilityModifiers;
25import org.eclipse.pde.api.tools.internal.provisional.builder.IApiProblemDetector;
26import org.eclipse.pde.api.tools.internal.provisional.builder.IReference;
27import org.eclipse.pde.api.tools.internal.provisional.descriptors.IElementDescriptor;
28import org.eclipse.pde.api.tools.internal.provisional.descriptors.IPackageDescriptor;
29import org.eclipse.pde.api.tools.internal.provisional.model.ApiTypeContainerVisitor;
30import org.eclipse.pde.api.tools.internal.provisional.model.IApiComponent;
31import org.eclipse.pde.api.tools.internal.provisional.model.IApiType;
32import org.eclipse.pde.api.tools.internal.provisional.model.IApiTypeContainer;
33import org.eclipse.pde.api.tools.internal.provisional.model.IApiTypeRoot;
34import org.eclipse.pde.api.tools.internal.provisional.problems.IApiProblem;
35import org.eclipse.pde.api.tools.internal.util.Util;
36 
37import com.ibm.icu.text.MessageFormat;
38 
39/**
40 * The reference analyzer
41 * 
42 * @since 1.1
43 */
44public class ReferenceAnalyzer {
45 
46        /**
47         * Natural log of 2.
48         */
49        private static final double LOG2 = Math.log(2);
50        
51        /**
52         * Constant used for controlling tracing in the search engine
53         */
54        private static boolean DEBUG = Util.DEBUG;        
55        
56        /**
57         * Empty result collection.
58         */
59        private static final IApiProblem[] EMPTY_RESULT = new IApiProblem[0];
60        /**
61         * No problem detector to use
62         */
63        private static final IApiProblemDetector[] NO_PROBLEM_DETECTORS = new IApiProblemDetector[0];
64        
65        /**
66         * Visits each class file, extracting references.
67         */
68        class Visitor extends ApiTypeContainerVisitor {
69                
70                private IProgressMonitor fMonitor = null;
71                
72                public Visitor(IProgressMonitor monitor) {
73                        fMonitor = monitor;
74                }
75                public boolean visitPackage(String packageName) {
76                        fMonitor.subTask(MessageFormat.format(BuilderMessages.ReferenceAnalyzer_checking_api_used_by, new String[]{packageName}));
77                        return true;
78                }
79                public void endVisitPackage(String packageName) {
80                        fMonitor.worked(1);
81                }
82                /* (non-Javadoc)
83                 * @see org.eclipse.pde.api.tools.model.component.ClassFileContainerVisitor#visit(java.lang.String, org.eclipse.pde.api.tools.model.component.IClassFile)
84                 */
85                public void visit(String packageName, IApiTypeRoot classFile) {
86                        if (!fMonitor.isCanceled()) {
87                                try {
88                                        //don't process inner/anonymous/local types, this is done in the extractor
89                                        if(classFile.getTypeName().indexOf('$') > -1) {
90                                                return;
91                                        }
92                                        IApiType type = classFile.getStructure();
93                                        if(type == null) {
94                                                //do nothing for bad class files
95                                                return;
96                                        }
97                                        List references = type.extractReferences(fAllReferenceKinds, null);
98                                        // keep potential matches
99                                        Iterator iterator = references.iterator();
100                                        while (iterator.hasNext()) {
101                                                IReference ref = (IReference) iterator.next();
102                                                // compute index of interested problem detectors
103                                                int index = getLog2(ref.getReferenceKind());
104                                                IApiProblemDetector[] detectors = fIndexedDetectors[index];
105                                                boolean added = false;
106                                                if (detectors != null) {
107                                                        for (int i = 0; i < detectors.length; i++) {
108                                                                IApiProblemDetector detector = detectors[i];
109                                                                if (detector.considerReference(ref)) {
110                                                                        if (!added) {
111                                                                                fReferences.add(ref);
112                                                                                added = true;
113                                                                        }
114                                                                }
115                                                        }
116                                                }
117                                        }
118                                } catch (CoreException e) {
119                                        fStatus.add(e.getStatus());
120                                }
121                        }
122                }
123        }
124        
125        /**
126         * Scan status
127         */
128        MultiStatus fStatus;        
129        
130        /**
131         * Bit mask of reference kinds that problem detectors care about.
132         */
133        int fAllReferenceKinds = 0;
134        
135        /**
136         * List of references to consider/resolve.
137         */
138        List fReferences = new LinkedList();
139        
140        /**
141         * Problem detectors indexed by the log base 2 of each reference kind they
142         * are interested in. Provides a fast way to hand references off to interested
143         * problem detectors.
144         */
145        IApiProblemDetector[][] fIndexedDetectors;
146 
147        /**
148         * Method used for initializing tracing
149         */
150        public static void setDebug(boolean debugValue) {
151                DEBUG = debugValue || Util.DEBUG;
152        }
153        
154        /**
155         * Performs the actual reference extraction and analysis.
156         * 
157         * @param scope the scope to extract and analyze references from
158         * @param detectors problem detectors to use
159         * @param monitor progress monitor
160         * @return any problems
161         * @throws CoreException
162         */
163        private IApiProblem[] analyze(IApiTypeContainer scope, IApiProblemDetector[] detectors, IProgressMonitor monitor) throws CoreException {
164                try {
165                        // 1. index problem detectors
166                        indexProblemDetectors(detectors);
167                        // 2. extract references
168                        SubMonitor localMonitor = SubMonitor.convert(monitor, BuilderMessages.ReferenceAnalyzer_analyzing_api, 3);
169                        localMonitor.subTask(BuilderMessages.ReferenceAnalyzer_analyzing_api_checking_use); 
170                        extractReferences(scope, localMonitor);
171                        localMonitor.worked(1);
172                        if (localMonitor.isCanceled()) {
173                                return EMPTY_RESULT;
174                        }
175                        // 3. resolve problematic references
176                        localMonitor.subTask(BuilderMessages.ReferenceAnalyzer_analyzing_api_checking_use);
177                        if (fReferences.size() != 0) {
178                                ReferenceResolver.resolveReferences(fReferences, localMonitor);
179                        }
180                        localMonitor.worked(1);
181                        if (localMonitor.isCanceled()) {
182                                return EMPTY_RESULT;
183                        }                
184                        // 4. create problems
185                        List allProblems = new LinkedList();
186                        localMonitor.subTask(BuilderMessages.ReferenceAnalyzer_analyzing_api_checking_use);
187                        for (int i = 0; i < detectors.length; i++) {
188                                IApiProblemDetector detector = detectors[i];
189                                List problems = detector.createProblems();
190                                allProblems.addAll(problems);
191                                if (localMonitor.isCanceled()) {
192                                        return EMPTY_RESULT;
193                                }
194                        }
195                        IApiProblem[] array = (IApiProblem[]) allProblems.toArray(new IApiProblem[allProblems.size()]);
196                        localMonitor.worked(1);
197                        localMonitor.done();
198                        return array;
199                } finally {
200                        // clean up
201                        fIndexedDetectors = null;
202                        fReferences.clear();
203                }
204        }
205        
206        /**
207         * Indexes the problem detectors by the reference kinds they are interested in.
208         * For example, a detector interested in a
209         * {@link org.eclipse.pde.api.tools.internal.provisional.search.ReferenceModifiers#REF_INSTANTIATE}
210         * will be in the 26th index (0x1 << 27, which is 2 ^ 26).
211         * Also initializes the bit mask of all interesting reference kinds.
212         * 
213         * @param detectors problem detectors
214         */
215        private void indexProblemDetectors(IApiProblemDetector[] detectors) {
216                fIndexedDetectors = new IApiProblemDetector[32][];
217                for (int i = 0; i < detectors.length; i++) {
218                        IApiProblemDetector detector = detectors[i];
219                        int kinds = detector.getReferenceKinds();
220                        fAllReferenceKinds |= kinds;
221                        int mask = 0x1;
222                        for (int bit = 0; bit < 32; bit++) {
223                                if ((mask & kinds) > 0) {
224                                        IApiProblemDetector[] indexed = fIndexedDetectors[bit];
225                                        if (indexed == null) {
226                                                fIndexedDetectors[bit] = new IApiProblemDetector[]{detector};
227                                        } else {
228                                                IApiProblemDetector[] next = new IApiProblemDetector[indexed.length + 1];
229                                                System.arraycopy(indexed, 0, next, 0, indexed.length);
230                                                next[indexed.length] = detector;
231                                                fIndexedDetectors[bit] = next;
232                                        }
233                                }
234                                mask = mask << 1;
235                        }
236                }
237        }
238        
239        /**
240         * log 2 (x) = ln(x) / ln(2)
241         * 
242         * @param bitConstant a single bit constant (0x1 << n)
243         * @return log base 2 of the constant (the power of 2 the constant is equal to)
244         */
245        int getLog2(int bitConstant) {
246                double logX = Math.log(bitConstant);
247                double pow = logX / LOG2;
248                return (int)Math.round(pow);
249        }        
250        
251        /**
252         * Scans the given scope extracting all reference information.
253         * 
254         * @param scope scope to scan
255         * @param monitor progress monitor
256         * @exception CoreException if the scan fails
257         */
258        private void extractReferences(IApiTypeContainer scope, IProgressMonitor monitor) throws CoreException {
259                fStatus = new MultiStatus(ApiPlugin.PLUGIN_ID, 0, BuilderMessages.ReferenceAnalyzer_api_analysis_error, null); 
260                String[] packageNames = scope.getPackageNames();
261                SubMonitor localMonitor = SubMonitor.convert(monitor, packageNames.length);
262                ApiTypeContainerVisitor visitor = new Visitor(localMonitor);
263                long start = System.currentTimeMillis();
264                try {
265                        scope.accept(visitor);
266                } catch (CoreException e) {
267                        fStatus.add(e.getStatus());
268                }
269                long end = System.currentTimeMillis();
270                if (!fStatus.isOK()) {
271                        throw new CoreException(fStatus);
272                }
273                localMonitor.done();
274                if (DEBUG) {
275                        System.out.println("Reference Analyzer: extracted " + fReferences.size() + " references in " + (end - start) + "ms"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
276                }
277        }        
278 
279        /**
280         * Analyzes the given {@link IApiComponent} within the given {@link IApiTypeContainer} (scope) and returns 
281         * a collection of detected {@link IApiProblem}s or an empty collection, never <code>null</code>
282         * @param component
283         * @param scope
284         * @param monitor
285         * @return the collection of detected {@link IApiProblem}s or an empty collection, never <code>null</code>
286         * @throws CoreException
287         */
288        public IApiProblem[] analyze(IApiComponent component, IApiTypeContainer scope, IProgressMonitor monitor) throws CoreException {
289                // build problem detectors
290                IApiProblemDetector[] detectors = buildProblemDetectors(component, monitor);
291                // analyze
292                return analyze(scope, detectors, monitor);
293        }
294        
295        /**
296         * Builds problem detectors to use when analyzing the given component.
297         * 
298         * @param component component to be analyzed
299         * @param monitor 
300         * 
301         * @return problem detectors
302         */
303        private IApiProblemDetector[] buildProblemDetectors(IApiComponent component, IProgressMonitor monitor) {
304                try {
305                        long start = System.currentTimeMillis();
306                        IApiComponent[] components = component.getBaseline().getPrerequisiteComponents(new IApiComponent[]{component});
307                        final ProblemDetectorBuilder visitor = new ProblemDetectorBuilder(component);
308                        for (int i = 0; i < components.length; i++) {
309                                Util.updateMonitor(monitor);
310                                IApiComponent prereq = components[i];
311                                if (!prereq.equals(component)) {
312                                        visitor.setOwningComponent(prereq);
313                                        try {
314                                                prereq.getApiDescription().accept(visitor, monitor);
315                                        } catch (CoreException e) {
316                                                ApiPlugin.log(e.getStatus());
317                                        }
318                                }
319                        }
320                        long end = System.currentTimeMillis();
321                        if (DEBUG) {
322                                System.out.println("Time to build problem detectors: " + (end-start) + "ms");  //$NON-NLS-1$//$NON-NLS-2$
323                        }                
324                        // add names from the leak component as well
325                        ApiDescriptionVisitor nameVisitor = new ApiDescriptionVisitor() {
326                                /* (non-Javadoc)
327                                 * @see org.eclipse.pde.api.tools.internal.provisional.ApiDescriptionVisitor#visitElement(org.eclipse.pde.api.tools.internal.provisional.descriptors.IElementDescriptor, org.eclipse.pde.api.tools.internal.provisional.IApiAnnotations)
328                                 */
329                                public boolean visitElement(IElementDescriptor element, IApiAnnotations description) {
330                                        if (element.getElementType() == IElementDescriptor.PACKAGE) {
331                                                if (VisibilityModifiers.isPrivate(description.getVisibility())) {
332                                                        visitor.addNonApiPackageName(((IPackageDescriptor)element).getName());
333                                                }
334                                        }
335                                        return false;
336                                }
337                        };
338                        component.getApiDescription().accept(nameVisitor, null);
339                        List detectors = visitor.getProblemDetectors();
340                        int size = detectors.size();
341                        if (size == 0) return NO_PROBLEM_DETECTORS;
342                        return (IApiProblemDetector[]) detectors.toArray(new IApiProblemDetector[size]);
343                } catch (CoreException e) {
344                        ApiPlugin.log(e);
345                }
346                return NO_PROBLEM_DETECTORS;
347        }
348}

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