This Bugzilla instance is a read-only archive of historic NetBeans bug reports. To report a bug in NetBeans please follow the project's instructions for reporting issues.

View | Details | Raw Unified | Return to bug 177396
Collapse All | Expand All

(-)a/java.editor/nbproject/project.xml (+18 lines)
Lines 203-208 Link Here
203
                    </run-dependency>
203
                    </run-dependency>
204
                </dependency>
204
                </dependency>
205
                <dependency>
205
                <dependency>
206
                    <code-name-base>org.netbeans.modules.java.platform</code-name-base>
207
                    <build-prerequisite/>
208
                    <compile-dependency/>
209
                    <run-dependency>
210
                        <release-version>1</release-version>
211
                        <specification-version>1.15</specification-version>
212
                    </run-dependency>
213
                </dependency>
214
                <dependency>
206
                    <code-name-base>org.netbeans.modules.java.preprocessorbridge</code-name-base>
215
                    <code-name-base>org.netbeans.modules.java.preprocessorbridge</code-name-base>
207
                    <build-prerequisite/>
216
                    <build-prerequisite/>
208
                    <compile-dependency/>
217
                    <compile-dependency/>
Lines 264-269 Link Here
264
                    </run-dependency>
273
                    </run-dependency>
265
                </dependency>
274
                </dependency>
266
                <dependency>
275
                <dependency>
276
                    <code-name-base>org.netbeans.modules.project.libraries</code-name-base>
277
                    <build-prerequisite/>
278
                    <compile-dependency/>
279
                    <run-dependency>
280
                        <release-version>1</release-version>
281
                        <specification-version>1.23</specification-version>
282
                    </run-dependency>
283
                </dependency>
284
                <dependency>
267
                    <code-name-base>org.netbeans.modules.projectapi</code-name-base>
285
                    <code-name-base>org.netbeans.modules.projectapi</code-name-base>
268
                    <build-prerequisite/>
286
                    <build-prerequisite/>
269
                    <compile-dependency/>
287
                    <compile-dependency/>
(-)a/java.editor/src/org/netbeans/modules/java/editor/overridden/AnnotationsHolder.java (-2 / +3 lines)
Lines 60-66 Link Here
60
 * @author Jan Lahoda
60
 * @author Jan Lahoda
61
 */
61
 */
62
public class AnnotationsHolder implements PropertyChangeListener {
62
public class AnnotationsHolder implements PropertyChangeListener {
63
    
63
64
    private static final Logger LOGGER = Logger.getLogger(AnnotationsHolder.class.getName());
64
    private static final Map<DataObject, AnnotationsHolder> file2Annotations = new HashMap<DataObject, AnnotationsHolder>();
65
    private static final Map<DataObject, AnnotationsHolder> file2Annotations = new HashMap<DataObject, AnnotationsHolder>();
65
    
66
    
66
    public static synchronized AnnotationsHolder get(FileObject file) {
67
    public static synchronized AnnotationsHolder get(FileObject file) {
Lines 82-88 Link Here
82
            
83
            
83
            return a;
84
            return a;
84
        } catch (IOException ex) {
85
        } catch (IOException ex) {
85
            IsOverriddenAnnotationHandler.LOG.log(Level.INFO, null, ex);
86
            LOGGER.log(Level.INFO, null, ex);
86
            
87
            
87
            return null;
88
            return null;
88
        }
89
        }
(-)a/java.editor/src/org/netbeans/modules/java/editor/overridden/Bundle.properties (-1 / +22 lines)
Lines 23-29 Link Here
23
# Contributor(s):
23
# Contributor(s):
24
#
24
#
25
# The Original Software is NetBeans. The Initial Developer of the Original
25
# The Original Software is NetBeans. The Initial Developer of the Original
26
# Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
26
# Software is Sun Microsystems, Inc. Portions Copyright 1997-2009 Sun
27
# Microsystems, Inc. All Rights Reserved.
27
# Microsystems, Inc. All Rights Reserved.
28
#
28
#
29
# If you wish your version of this file to be governed by only the CDDL
29
# If you wish your version of this file to be governed by only the CDDL
Lines 51-53 Link Here
51
NAME_AnonynmousInner=anonymous inner
51
NAME_AnonynmousInner=anonymous inner
52
52
53
CTL_IsOverriddenAnnotationAction=Overriden Annotation
53
CTL_IsOverriddenAnnotationAction=Overriden Annotation
54
CTL_GoToImplementation=Go to Implementation
55
goto-implementation=Go to Implementation
56
57
LAB_IsOverridenAnnotation-override-is-overridden-combined=Overrides and is overridden
58
TP_COMBINED-override-is-overridden-combined=Overrides and is overridden
59
LAB_IsOverridenAnnotation-implements-is-overridden-combined=Implements and is overridden
60
TP_COMBINED-implements-is-overridden-combined=Implements and is overridden
61
#XXX: inside interfaces, but this should ideally be overrides/has implementations:
62
LAB_IsOverridenAnnotation-implements-has-implementations-combined=Implements and has implementations
63
TP_COMBINED-implements-has-implementations-combined=Implements and has implementations
64
LAB_IsOverriddenAnnotation=Is Overridden
65
LAB_OverridesAnnotation=Overrides
66
LAB_ImplementsAnnotation=Implements
67
LAB_HasImplementationsAnnotation=Has Implementations
68
69
LBL_NoMethod=No Method or Type
70
LBL_NoOverridingMethod=No overridding method found
71
LBL_NoOverridingType=No overridding type found
72
ERR_CycleInDependencies=Cycle in dependencies
73
LBL_ImplementorsOverriders=Implementors/Overridders
74
ERR_NoDependencies=Cannot detect project dependencies
(-)a/java.editor/src/org/netbeans/modules/java/editor/overridden/ComputeAnnotations.java (+196 lines)
Line 0 Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
5
 *
6
 * The contents of this file are subject to the terms of either the GNU
7
 * General Public License Version 2 only ("GPL") or the Common
8
 * Development and Distribution License("CDDL") (collectively, the
9
 * "License"). You may not use this file except in compliance with the
10
 * License. You can obtain a copy of the License at
11
 * http://www.netbeans.org/cddl-gplv2.html
12
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
13
 * specific language governing permissions and limitations under the
14
 * License.  When distributing the software, include this License Header
15
 * Notice in each file and include the License file at
16
 * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
17
 * particular file as subject to the "Classpath" exception as provided
18
 * by Sun in the GPL Version 2 section of the License file that
19
 * accompanied this code. If applicable, add the following below the
20
 * License Header, with the fields enclosed by brackets [] replaced by
21
 * your own identifying information:
22
 * "Portions Copyrighted [year] [name of copyright owner]"
23
 *
24
 * If you wish your version of this file to be governed by only the CDDL
25
 * or only the GPL Version 2, indicate your decision by adding
26
 * "[Contributor] elects to include this software in this distribution
27
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
28
 * single choice of license, a recipient has the option to distribute
29
 * your version of this file under either the CDDL, the GPL Version 2 or
30
 * to extend the choice of license to its licensees as provided above.
31
 * However, if you add GPL Version 2 code and therefore, elected the GPL
32
 * Version 2 license, then the option applies only if the new code is
33
 * made subject to such option by the copyright holder.
34
 *
35
 * Contributor(s):
36
 *
37
 * Portions Copyrighted 2009 Sun Microsystems, Inc.
38
 */
39
package org.netbeans.modules.java.editor.overridden;
40
41
import com.sun.source.tree.Tree;
42
import java.util.Collection;
43
import java.util.Collections;
44
import java.util.LinkedList;
45
import java.util.List;
46
import java.util.Map;
47
import java.util.Map.Entry;
48
import java.util.concurrent.atomic.AtomicBoolean;
49
import java.util.logging.Level;
50
import java.util.logging.Logger;
51
import javax.lang.model.element.Element;
52
import javax.swing.text.BadLocationException;
53
import javax.swing.text.Position;
54
import javax.swing.text.StyledDocument;
55
import org.netbeans.api.java.source.CompilationInfo;
56
import org.netbeans.api.java.source.ElementHandle;
57
import org.netbeans.api.java.source.JavaParserResultTask;
58
import org.netbeans.api.java.source.JavaSource.Phase;
59
import org.netbeans.modules.parsing.api.Snapshot;
60
import org.netbeans.modules.parsing.spi.Parser.Result;
61
import org.netbeans.modules.parsing.spi.Scheduler;
62
import org.netbeans.modules.parsing.spi.SchedulerEvent;
63
import org.netbeans.modules.parsing.spi.SchedulerTask;
64
import org.netbeans.modules.parsing.spi.TaskFactory;
65
import org.openide.text.NbDocument;
66
67
/**
68
 *
69
 * @author lahvac
70
 */
71
public class ComputeAnnotations extends JavaParserResultTask<Result> {
72
73
    private final AtomicBoolean cancel = new AtomicBoolean();
74
    
75
    public ComputeAnnotations() {
76
        super(Phase.RESOLVED);
77
    }
78
79
    @Override
80
    public void run(Result result, SchedulerEvent event) {
81
        cancel.set(false);
82
        
83
        CompilationInfo info = CompilationInfo.get(result);
84
85
        if (info.getChangedTree() != null) {
86
            //XXX: currently only method bodies are rebuilt.
87
            return ;
88
        }
89
        
90
        long start = System.currentTimeMillis();
91
        StyledDocument doc = (StyledDocument) result.getSnapshot().getSource().getDocument(false);
92
93
        if (doc == null) {
94
            return ;
95
        }
96
        
97
        List<IsOverriddenAnnotation> annotations = new LinkedList<IsOverriddenAnnotation>();
98
99
        createAnnotations(info, doc, new ComputeOverriding(cancel).process(info), false, annotations);
100
        createAnnotations(info, doc, new ComputeOverriders(cancel).process(info, null, null, false), true, annotations);
101
102
        if (cancel.get()) return ;
103
        
104
        AnnotationsHolder.get(info.getFileObject()).setNewAnnotations(annotations);
105
106
        long end = System.currentTimeMillis();
107
108
        Logger.getLogger("TIMER").log(Level.FINE, "Is Overridden Annotations", new Object[] {info.getFileObject(), end - start});
109
    }
110
111
    private void createAnnotations(CompilationInfo info, StyledDocument doc, Map<ElementHandle<? extends Element>, List<ElementDescription>> descriptions, boolean overridden, List<IsOverriddenAnnotation> annotations) {
112
        if (descriptions != null) {
113
            for (Entry<ElementHandle<? extends Element>, List<ElementDescription>> e : descriptions.entrySet()) {
114
                Element ee = e.getKey().resolve(info);
115
                Tree t = info.getTrees().getTree(ee);
116
117
                if (t == null) {
118
                    //XXX: log
119
                    continue;
120
                }
121
122
                AnnotationType type;
123
                String dn;
124
125
                if (overridden) {
126
                    if (ee.getEnclosingElement().getKind().isInterface() || ee.getKind().isInterface()) {
127
                        type = AnnotationType.HAS_IMPLEMENTATION;
128
                        dn = "Is Implemented";
129
                    } else {
130
                        type = AnnotationType.IS_OVERRIDDEN;
131
                        dn = "Is Overridden";
132
                    }
133
                } else {
134
                    if (ee.getEnclosingElement().getKind().isInterface() || ee.getKind().isInterface()) {
135
                        type = AnnotationType.IMPLEMENTS;
136
                        dn = "Implements";
137
                    } else {
138
                        type = AnnotationType.OVERRIDES;
139
                        dn = "Overrides";
140
                    }
141
                }
142
143
                Position pos = getPosition(doc, (int) info.getTrees().getSourcePositions().getStartPosition(info.getCompilationUnit(), t));
144
                
145
                annotations.add(new IsOverriddenAnnotation(doc, pos, type, dn, e.getValue()));
146
            }
147
        }
148
    }
149
150
    @Override
151
    public int getPriority() {
152
        return Integer.MAX_VALUE;
153
    }
154
155
    @Override
156
    public Class<? extends Scheduler> getSchedulerClass() {
157
        return Scheduler.EDITOR_SENSITIVE_TASK_SCHEDULER;
158
    }
159
160
    @Override
161
    public void cancel() {
162
        cancel.set(true);
163
    }
164
    
165
    private static Position getPosition(final StyledDocument doc, final int offset) {
166
        class Impl implements Runnable {
167
            private Position pos;
168
            public void run() {
169
                if (offset < 0 || offset >= doc.getLength())
170
                    return ;
171
172
                try {
173
                    pos = doc.createPosition(offset - NbDocument.findLineColumn(doc, offset));
174
                } catch (BadLocationException ex) {
175
                    //should not happen?
176
                    Logger.getLogger(ComputeAnnotations.class.getName()).log(Level.FINE, null, ex);
177
                }
178
            }
179
        }
180
181
        Impl i = new Impl();
182
183
        doc.render(i);
184
185
        return i.pos;
186
    }
187
188
    public static final class FactoryImpl extends TaskFactory {
189
190
        @Override
191
        public Collection<? extends SchedulerTask> create(Snapshot snapshot) {
192
            return Collections.singleton(new ComputeAnnotations());
193
        }
194
        
195
    }
196
}
(-)a/java.editor/src/org/netbeans/modules/java/editor/overridden/ComputeOverriders.java (+575 lines)
Line 0 Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
5
 *
6
 * The contents of this file are subject to the terms of either the GNU
7
 * General Public License Version 2 only ("GPL") or the Common
8
 * Development and Distribution License("CDDL") (collectively, the
9
 * "License"). You may not use this file except in compliance with the
10
 * License. You can obtain a copy of the License at
11
 * http://www.netbeans.org/cddl-gplv2.html
12
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
13
 * specific language governing permissions and limitations under the
14
 * License.  When distributing the software, include this License Header
15
 * Notice in each file and include the License file at
16
 * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
17
 * particular file as subject to the "Classpath" exception as provided
18
 * by Sun in the GPL Version 2 section of the License file that
19
 * accompanied this code. If applicable, add the following below the
20
 * License Header, with the fields enclosed by brackets [] replaced by
21
 * your own identifying information:
22
 * "Portions Copyrighted [year] [name of copyright owner]"
23
 *
24
 * If you wish your version of this file to be governed by only the CDDL
25
 * or only the GPL Version 2, indicate your decision by adding
26
 * "[Contributor] elects to include this software in this distribution
27
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
28
 * single choice of license, a recipient has the option to distribute
29
 * your version of this file under either the CDDL, the GPL Version 2 or
30
 * to extend the choice of license to its licensees as provided above.
31
 * However, if you add GPL Version 2 code and therefore, elected the GPL
32
 * Version 2 license, then the option applies only if the new code is
33
 * made subject to such option by the copyright holder.
34
 *
35
 * Contributor(s):
36
 *
37
 * Portions Copyrighted 2009 Sun Microsystems, Inc.
38
 */
39
40
package org.netbeans.modules.java.editor.overridden;
41
42
import java.awt.Point;
43
import java.lang.reflect.InvocationTargetException;
44
import java.lang.reflect.Method;
45
import java.net.URL;
46
import java.util.ArrayList;
47
import java.util.Collections;
48
import java.util.EnumSet;
49
import java.util.HashMap;
50
import java.util.HashSet;
51
import java.util.LinkedHashMap;
52
import java.util.LinkedList;
53
import java.util.List;
54
import java.util.Map;
55
import java.util.Set;
56
import java.util.concurrent.atomic.AtomicBoolean;
57
import java.util.logging.Level;
58
import java.util.logging.Logger;
59
import javax.lang.model.element.Element;
60
import javax.lang.model.element.ExecutableElement;
61
import javax.lang.model.element.TypeElement;
62
import javax.lang.model.util.ElementFilter;
63
import javax.lang.model.util.Types;
64
import org.netbeans.api.java.classpath.ClassPath;
65
import org.netbeans.api.java.queries.SourceForBinaryQuery;
66
import org.netbeans.api.java.source.ClassIndex;
67
import org.netbeans.api.java.source.ClassIndex.SearchKind;
68
import org.netbeans.api.java.source.ClassIndex.SearchScope;
69
import org.netbeans.api.java.source.ClasspathInfo;
70
import org.netbeans.api.java.source.CompilationController;
71
import org.netbeans.api.java.source.CompilationInfo;
72
import org.netbeans.api.java.source.ElementHandle;
73
import org.netbeans.api.java.source.JavaSource;
74
import org.netbeans.api.java.source.SourceUtils;
75
import org.netbeans.api.java.source.Task;
76
import org.netbeans.spi.java.classpath.support.ClassPathSupport;
77
import org.openide.DialogDisplayer;
78
import org.openide.NotifyDescriptor;
79
import org.openide.filesystems.FileObject;
80
import org.openide.filesystems.FileStateInvalidException;
81
import org.openide.filesystems.URLMapper;
82
import org.openide.util.Exceptions;
83
import org.openide.util.Lookup;
84
import org.openide.util.NbBundle;
85
import org.openide.util.TopologicalSortException;
86
import org.openide.util.Utilities;
87
88
/**
89
 *
90
 * @author Jan Lahoda
91
 */
92
public class ComputeOverriders {
93
94
    private static final Logger LOG = Logger.getLogger(ComputeOverriders.class.getName());
95
96
    private final AtomicBoolean cancel;
97
98
    public ComputeOverriders(AtomicBoolean cancel) {
99
        this.cancel = cancel;
100
    }
101
    
102
    private static Set<URL> findReverseSourceRoots(final URL thisSourceRoot, Map<URL, List<URL>> sourceDeps, final FileObject thisFile) {
103
        long startTime = System.currentTimeMillis();
104
105
        try {
106
            //TODO: from SourceUtils (which filters out source roots that do not belong to open projects):
107
            //Create inverse dependencies
108
            final Map<URL, List<URL>> inverseDeps = new HashMap<URL, List<URL>> ();
109
            for (Map.Entry<URL,List<URL>> entry : sourceDeps.entrySet()) {
110
                final URL u1 = entry.getKey();
111
                final List<URL> l1 = entry.getValue();
112
                for (URL u2 : l1) {
113
                    List<URL> l2 = inverseDeps.get(u2);
114
                    if (l2 == null) {
115
                        l2 = new ArrayList<URL>();
116
                        inverseDeps.put (u2,l2);
117
                    }
118
                    l2.add (u1);
119
                }
120
            }
121
            //Collect dependencies
122
            final Set<URL> result = new HashSet<URL>();
123
            final LinkedList<URL> todo = new LinkedList<URL> ();
124
            todo.add (thisSourceRoot);
125
            while (!todo.isEmpty()) {
126
                final URL u = todo.removeFirst();
127
                if (!result.contains(u)) {
128
                    result.add (u);
129
                    final List<URL> ideps = inverseDeps.get(u);
130
                    if (ideps != null) {
131
                        todo.addAll (ideps);
132
                    }
133
                }
134
            }
135
            return result;
136
        } finally {
137
            long endTime = System.currentTimeMillis();
138
139
            Logger.getLogger("TIMER").log(Level.FINE, "Find Reverse Source Roots", //NOI18N
140
                    new Object[]{thisFile, endTime - startTime});
141
        }
142
    }
143
144
    private static FileObject findSourceRoot(FileObject file) {
145
        final ClassPath cp = ClassPath.getClassPath(file, ClassPath.SOURCE);
146
        if (cp != null) {
147
            return cp.findOwnerRoot(file);
148
        }
149
        //Null is a valid value for files which have no source path (default filesystem).
150
        return null;
151
    }
152
153
    private Set<URL> findBinaryRootsForSourceRoot(FileObject sourceRoot, Map<URL, List<URL>> binaryDeps) {
154
//      BinaryForSourceQuery.findBinaryRoots(thisSourceRoot).getRoots();
155
        Set<URL> result = new HashSet<URL>();
156
157
        for (URL bin : binaryDeps.keySet()) {
158
            if (cancel.get()) return Collections.emptySet();
159
            for (FileObject s : SourceForBinaryQuery.findSourceRoots(bin).getRoots()) {
160
                if (s == sourceRoot) {
161
                    result.add(bin);
162
                }
163
            }
164
        }
165
166
        return result;
167
    }
168
169
    Map<ElementHandle<? extends Element>, List<ElementDescription>> process(CompilationInfo info, TypeElement te, ExecutableElement ee, boolean interactive) {
170
        long startTime = System.currentTimeMillis();
171
172
        try {
173
            return processImpl(info, te, ee, interactive);
174
        } finally {
175
            Logger.getLogger("TIMER").log(Level.FINE, "Overridden - Total", //NOI18N
176
                new Object[] {info.getFileObject(), System.currentTimeMillis() - startTime});
177
        }
178
    }
179
180
    private Map<ElementHandle<? extends Element>, List<ElementDescription>> processImpl(CompilationInfo info, TypeElement te, ExecutableElement ee, boolean interactive) {
181
        FileObject file = info.getFileObject();
182
        FileObject thisSourceRoot = findSourceRoot(file);
183
        
184
        if (thisSourceRoot == null) {
185
            return null;
186
        }
187
188
189
        //XXX: special case "this" source root (no need to create a new JS and load the classes again for it):
190
//        reverseSourceRoots.add(thisSourceRoot);
191
192
//        LOG.log(Level.FINE, "reverseSourceRoots: {0}", reverseSourceRoots); //NOI18N
193
194
//                if (LOG.isLoggable(Level.FINE)) {
195
//                    LOG.log(Level.FINE, "method: {0}", ee.toString()); //NOI18N
196
//                }
197
198
199
        final Map<ElementHandle<TypeElement>, List<ElementHandle<ExecutableElement>>> methods = new HashMap<ElementHandle<TypeElement>, List<ElementHandle<ExecutableElement>>>();
200
201
        if (ee == null) {
202
            if (te == null) {
203
                fillInMethods(info.getTopLevelElements(), methods);
204
            } else {
205
                methods.put(ElementHandle.create(te), Collections.<ElementHandle<ExecutableElement>>emptyList());
206
            }
207
        } else {
208
            TypeElement owner = (TypeElement) ee.getEnclosingElement();
209
210
            methods.put(ElementHandle.create(owner), Collections.singletonList(ElementHandle.create(ee)));
211
        }
212
213
        final Map<ElementHandle<? extends Element>, List<ElementDescription>> overriding = new HashMap<ElementHandle<? extends Element>, List<ElementDescription>>();
214
215
        long startTime = System.currentTimeMillis();
216
        long[] classIndexTime = new long[1];
217
        final Map<URL, Map<ElementHandle<TypeElement>, Set<ElementHandle<TypeElement>>>> users = computeUsers(info, thisSourceRoot, methods.keySet(), classIndexTime, interactive);
218
        long endTime = System.currentTimeMillis();
219
220
        if (users == null) {
221
            return null;
222
        }
223
224
        Logger.getLogger("TIMER").log(Level.FINE, "Overridden Candidates - Class Index", //NOI18N
225
            new Object[] {file, classIndexTime[0]});
226
        Logger.getLogger("TIMER").log(Level.FINE, "Overridden Candidates - Total", //NOI18N
227
            new Object[] {file, endTime - startTime});
228
229
        for (Map.Entry<URL, Map<ElementHandle<TypeElement>, Set<ElementHandle<TypeElement>>>> data : users.entrySet()) {
230
            for (Map.Entry<ElementHandle<TypeElement>, Set<ElementHandle<TypeElement>>> deps : data.getValue().entrySet()) {
231
                if (cancel.get()) return null;
232
                findOverriddenAnnotations(data.getKey(), deps.getValue(), deps.getKey(), methods.get(deps.getKey()), overriding);
233
            }
234
        }
235
236
        return overriding;
237
    }
238
    private static final ClassPath EMPTY = ClassPathSupport.createClassPath(new URL[0]);
239
240
    private static void fillInMethods(Iterable<? extends TypeElement> types, Map<ElementHandle<TypeElement>, List<ElementHandle<ExecutableElement>>> methods) {
241
        for (TypeElement te : types) {
242
            List<ElementHandle<ExecutableElement>> l = new LinkedList<ElementHandle<ExecutableElement>>();
243
244
            for (ExecutableElement ee : ElementFilter.methodsIn(te.getEnclosedElements())) {
245
                l.add(ElementHandle.create(ee));
246
            }
247
248
            methods.put(ElementHandle.create(te), l);
249
250
            fillInMethods(ElementFilter.typesIn(te.getEnclosedElements()), methods);
251
        }
252
    }
253
    private Set<ElementHandle<TypeElement>> computeUsers(URL source, Set<ElementHandle<TypeElement>> base, long[] classIndexCumulative) {
254
        ClasspathInfo cpinfo = ClasspathInfo.create(EMPTY, EMPTY, ClassPathSupport.createClassPath(source));
255
        
256
        return computeUsers(cpinfo, ClassIndex.SearchScope.SOURCE, base, classIndexCumulative);
257
    }
258
    
259
    private Set<ElementHandle<TypeElement>> computeUsers(ClasspathInfo cpinfo, SearchScope scope, Set<ElementHandle<TypeElement>> base, long[] classIndexCumulative) {
260
        long startTime = System.currentTimeMillis();
261
262
        try {
263
            List<ElementHandle<TypeElement>> l = new LinkedList<ElementHandle<TypeElement>>(base);
264
            Set<ElementHandle<TypeElement>> result = new HashSet<ElementHandle<TypeElement>>();
265
266
            while (!l.isEmpty()) {
267
                if (cancel.get()) return null;
268
                
269
                ElementHandle<TypeElement> eh = l.remove(0);
270
271
                result.add(eh);
272
                Set<ElementHandle<TypeElement>> typeElements = cpinfo.getClassIndex().getElements(eh, Collections.singleton(SearchKind.IMPLEMENTORS), EnumSet.of(scope));
273
                //XXX: Canceling
274
                if (typeElements != null) {
275
                    l.addAll(typeElements);
276
                }
277
            }
278
            return result;
279
        } finally {
280
            classIndexCumulative[0] += (System.currentTimeMillis() - startTime);
281
        }
282
    }
283
284
    static List<URL> reverseSourceRootsInOrderOverride;
285
286
    private List<URL> reverseSourceRootsInOrder(CompilationInfo info, URL thisSourceRoot, FileObject thisSourceRootFO, Map<URL, List<URL>> sourceDeps, Map<URL, List<URL>> binaryDeps, boolean interactive) {
287
        if (reverseSourceRootsInOrderOverride != null) {
288
            return reverseSourceRootsInOrderOverride;
289
        }
290
291
        Set<URL> sourceRootsSet;
292
293
        if (sourceDeps.containsKey(thisSourceRoot)) {
294
            sourceRootsSet = findReverseSourceRoots(thisSourceRoot, sourceDeps, info.getFileObject());
295
        } else {
296
            sourceRootsSet = new HashSet<URL>();
297
298
            for (URL binary : findBinaryRootsForSourceRoot(thisSourceRootFO, binaryDeps)) {
299
                List<URL> deps = binaryDeps.get(binary);
300
301
                if (deps != null) {
302
                    sourceRootsSet.addAll(deps);
303
                }
304
            }
305
        }
306
        
307
        List<URL> sourceRoots;
308
        try {
309
            sourceRoots = new LinkedList<URL>(Utilities.topologicalSort(sourceDeps.keySet(), sourceDeps));
310
        } catch (TopologicalSortException ex) {
311
            if (interactive) {
312
                Exceptions.attachLocalizedMessage(ex,NbBundle.getMessage(GoToImplementation.class, "ERR_CycleInDependencies"));
313
                Exceptions.printStackTrace(ex);
314
            } else {
315
                LOG.log(Level.FINE, null, ex);
316
            }
317
            return null;
318
        }
319
320
        sourceRoots.retainAll(sourceRootsSet);
321
322
        Collections.reverse(sourceRoots);
323
324
        return sourceRoots;
325
    }
326
    
327
    private Map<URL, Map<ElementHandle<TypeElement>, Set<ElementHandle<TypeElement>>>> computeUsers(CompilationInfo info, FileObject thisSourceRoot, Set<ElementHandle<TypeElement>> baseHandles, long[] classIndexCumulative, boolean interactive) {
328
        Map<URL, List<URL>> sourceDeps = getDependencies(false);
329
        Map<URL, List<URL>> binaryDeps = getDependencies(true);
330
331
        if (sourceDeps == null || binaryDeps == null) {
332
            if (interactive) {
333
                NotifyDescriptor nd = new NotifyDescriptor.Message(NbBundle.getMessage(GoToImplementation.class, "ERR_NoDependencies"), NotifyDescriptor.ERROR_MESSAGE);
334
335
                DialogDisplayer.getDefault().notifyLater(nd);
336
            } else {
337
                LOG.log(Level.FINE, NbBundle.getMessage(GoToImplementation.class, "ERR_NoDependencies"));
338
            }
339
            
340
            return null;
341
        }
342
343
        URL thisSourceRootURL;
344
345
        try {
346
            thisSourceRootURL = thisSourceRoot.getURL();
347
        } catch (FileStateInvalidException ex) {
348
            Exceptions.printStackTrace(ex);
349
            return null;
350
        }
351
352
        List<URL> sourceRoots = reverseSourceRootsInOrder(info, thisSourceRootURL, thisSourceRoot, sourceDeps, binaryDeps, interactive);
353
354
        if (sourceRoots == null) {
355
            return null;
356
        }
357
358
        Map<ElementHandle<TypeElement>, Set<ElementHandle<TypeElement>>> auxHandles = new HashMap<ElementHandle<TypeElement>, Set<ElementHandle<TypeElement>>>();
359
360
        if (!sourceDeps.containsKey(thisSourceRootURL)) {
361
            Set<URL> binaryRoots = new HashSet<URL>();
362
            
363
            for (URL sr : sourceRoots) {
364
                List<URL> deps = sourceDeps.get(sr);
365
366
                if (deps != null) {
367
                    binaryRoots.addAll(deps);
368
                }
369
            }
370
371
            binaryRoots.retainAll(binaryDeps.keySet());
372
373
            for (ElementHandle<TypeElement> handle : baseHandles) {
374
                Set<ElementHandle<TypeElement>> types = computeUsers(ClasspathInfo.create(EMPTY, ClassPathSupport.createClassPath(binaryRoots.toArray(new URL[0])), EMPTY), SearchScope.DEPENDENCIES, Collections.singleton(handle), classIndexCumulative);
375
376
                if (types == null/*canceled*/ || cancel.get()) {
377
                    return null;
378
                }
379
                
380
                auxHandles.put(handle, types);
381
            }
382
        }
383
        
384
        Map<URL, Map<ElementHandle<TypeElement>, Set<ElementHandle<TypeElement>>>> result = new LinkedHashMap<URL, Map<ElementHandle<TypeElement>, Set<ElementHandle<TypeElement>>>>();
385
386
        for (URL file : sourceRoots) {
387
            for (ElementHandle<TypeElement> base : baseHandles) {
388
                if (cancel.get()) return null;
389
                
390
                Set<ElementHandle<TypeElement>> baseTypes = new HashSet<ElementHandle<TypeElement>>();
391
392
                baseTypes.add(base);
393
394
                Set<ElementHandle<TypeElement>> aux = auxHandles.get(base);
395
396
                if (aux != null) {
397
                    baseTypes.addAll(aux);
398
                }
399
400
                for (URL dep : sourceDeps.get(file)) {
401
                    Map<ElementHandle<TypeElement>, Set<ElementHandle<TypeElement>>> depTypesMulti = result.get(dep);
402
                    Set<ElementHandle<TypeElement>> depTypes = depTypesMulti != null ? depTypesMulti.get(base) : null;
403
404
                    if (depTypes != null) {
405
                        baseTypes.addAll(depTypes);
406
                    }
407
                }
408
409
                Set<ElementHandle<TypeElement>> types = computeUsers(file, baseTypes, classIndexCumulative);
410
411
                if (types == null/*canceled*/ || cancel.get()) {
412
                    return null;
413
                }
414
                
415
                types.removeAll(baseTypes);
416
417
                Map<ElementHandle<TypeElement>, Set<ElementHandle<TypeElement>>> currentUsers = result.get(file);
418
419
                if (currentUsers == null) {
420
                    result.put(file, currentUsers = new LinkedHashMap<ElementHandle<TypeElement>, Set<ElementHandle<TypeElement>>>());
421
                }
422
423
                currentUsers.put(base, types);
424
            }
425
        }
426
427
        return result;
428
    }
429
430
    private void findOverriddenAnnotations(
431
            URL sourceRoot,
432
            final Set<ElementHandle<TypeElement>> users,
433
            final ElementHandle<TypeElement> originalType,
434
            final List<ElementHandle<ExecutableElement>> methods,
435
            final Map<ElementHandle<? extends Element>, List<ElementDescription>> overriding) {
436
        if (!users.isEmpty()) {
437
            FileObject sourceRootFile = URLMapper.findFileObject(sourceRoot);
438
            ClasspathInfo cpinfo = ClasspathInfo.create(sourceRootFile);
439
440
            JavaSource js = JavaSource.create(cpinfo);
441
442
            try {
443
                js.runUserActionTask(new Task<CompilationController>() {
444
                    public void run(CompilationController controller) throws Exception {
445
                        Set<Element> seenElements = new HashSet<Element>();
446
                        Element resolvedOriginalType = originalType.resolve(controller);
447
448
                        if (resolvedOriginalType == null) {
449
                            return ;
450
                        }
451
                        
452
                        for (ElementHandle<TypeElement> typeHandle : users) {
453
                            if (cancel.get()) return ;
454
                            TypeElement type = typeHandle.resolve(controller);
455
456
                            if (type == null || !seenElements.add(type)) {
457
                                continue;
458
                            }
459
460
                            Types types = controller.getTypes();
461
462
                            if (types.isSubtype(types.erasure(type.asType()), types.erasure(resolvedOriginalType.asType()))) {
463
                                List<ElementDescription> classOverriders = overriding.get(originalType);
464
465
                                if (classOverriders == null) {
466
                                    overriding.put(originalType, classOverriders = new LinkedList<ElementDescription>());
467
                                }
468
469
                                classOverriders.add(new ElementDescription(controller, type, true));
470
471
                                for (ElementHandle<ExecutableElement> originalMethodHandle : methods) {
472
                                    ExecutableElement originalMethod = originalMethodHandle.resolve(controller);
473
474
                                    if (originalMethod != null) {
475
                                        ExecutableElement overrider = getImplementationOf(controller, originalMethod, type);
476
477
                                        if (overrider == null) {
478
                                            continue;
479
                                        }
480
481
                                        List<ElementDescription> overriddingMethods = overriding.get(originalMethodHandle);
482
483
                                        if (overriddingMethods == null) {
484
                                            overriding.put(originalMethodHandle, overriddingMethods = new ArrayList<ElementDescription>());
485
                                        }
486
487
                                        overriddingMethods.add(new ElementDescription(controller, overrider, true));
488
                                    } else {
489
                                        Logger.getLogger("global").log(Level.SEVERE, "IsOverriddenAnnotationHandler: originalMethod == null!"); //NOI18N
490
                                    }
491
                                }
492
                            }
493
                        }
494
                    }
495
                }, true);
496
            } catch (Exception e) {
497
                Exceptions.printStackTrace(e);
498
            }
499
        }
500
    }
501
502
    private static ExecutableElement getImplementationOf(CompilationInfo info, ExecutableElement overridee, TypeElement implementor) {
503
        for (ExecutableElement overrider : ElementFilter.methodsIn(implementor.getEnclosedElements())) {
504
            if (info.getElements().overrides(overrider, overridee, implementor)) {
505
                return overrider;
506
            }
507
        }
508
509
        return null;
510
    }
511
512
    static void performGoToAction(List<ElementDescription> declarations, Point position) {
513
        String caption = NbBundle.getMessage(GoToImplementation.class, "LBL_ImplementorsOverriders");
514
515
        PopupUtil.showPopup(new IsOverriddenPopup(caption, declarations), caption, position.x, position.y, true, 0);
516
    }
517
518
    static Map<URL, List<URL>> dependenciesOverride;
519
    
520
    private static Map<URL, List<URL>> getDependencies(boolean binary) {
521
        if (dependenciesOverride != null) {
522
            return dependenciesOverride;
523
        }
524
        
525
        ClassLoader l = Lookup.getDefault().lookup(ClassLoader.class);
526
527
        if (l == null) {
528
            return null;
529
        }
530
531
        Class clazz = null;
532
        String method = null;
533
534
        try {
535
            clazz = l.loadClass("org.netbeans.modules.parsing.impl.indexing.friendapi.IndexingController");
536
            method = binary ? "getBinaryRootDependencies" : "getRootDependencies";
537
        } catch (ClassNotFoundException ex) {
538
            Logger.getLogger(GoToImplementation.class.getName()).log(Level.FINE, null, ex);
539
            try {
540
                clazz = l.loadClass("org.netbeans.modules.parsing.impl.indexing.RepositoryUpdater");
541
                method = binary ? "getDependencies" : "doesnotexist";
542
            } catch (ClassNotFoundException inner) {
543
                Logger.getLogger(GoToImplementation.class.getName()).log(Level.FINE, null, inner);
544
                return null;
545
            }
546
        }
547
548
        try {
549
            Method getDefault = clazz.getDeclaredMethod("getDefault");
550
            Object instance = getDefault.invoke(null);
551
            Method dependenciesMethod = clazz.getDeclaredMethod(method);
552
553
            return (Map<URL, List<URL>>) dependenciesMethod.invoke(instance);
554
        } catch (IllegalAccessException ex) {
555
            Logger.getLogger(GoToImplementation.class.getName()).log(Level.FINE, null, ex);
556
            return null;
557
        } catch (IllegalArgumentException ex) {
558
            Logger.getLogger(GoToImplementation.class.getName()).log(Level.FINE, null, ex);
559
            return null;
560
        } catch (InvocationTargetException ex) {
561
            Logger.getLogger(GoToImplementation.class.getName()).log(Level.FINE, null, ex);
562
            return null;
563
        } catch (NoSuchMethodException ex) {
564
            Logger.getLogger(GoToImplementation.class.getName()).log(Level.FINE, null, ex);
565
            return null;
566
        } catch (SecurityException ex) {
567
            Logger.getLogger(GoToImplementation.class.getName()).log(Level.FINE, null, ex);
568
            return null;
569
        } catch (ClassCastException ex) {
570
            Logger.getLogger(GoToImplementation.class.getName()).log(Level.FINE, null, ex);
571
            return null;
572
        }
573
    }
574
575
}
(-)a/java.editor/src/org/netbeans/modules/java/editor/overridden/IsOverriddenAnnotationHandler.java (-471 / +17 lines)
Lines 42-60 Link Here
42
package org.netbeans.modules.java.editor.overridden;
42
package org.netbeans.modules.java.editor.overridden;
43
43
44
import com.sun.source.tree.CompilationUnitTree;
44
import com.sun.source.tree.CompilationUnitTree;
45
import com.sun.source.tree.Tree;
46
import java.io.IOException;
47
import java.net.URL;
48
import java.util.ArrayList;
45
import java.util.ArrayList;
49
import java.util.Collection;
50
import java.util.Collections;
51
import java.util.HashMap;
46
import java.util.HashMap;
52
import java.util.HashSet;
47
import java.util.HashSet;
53
import java.util.EnumSet;
54
import java.util.LinkedList;
48
import java.util.LinkedList;
55
import java.util.List;
49
import java.util.List;
56
import java.util.Map;
50
import java.util.Map;
57
import java.util.Set;
51
import java.util.Set;
52
import java.util.concurrent.atomic.AtomicBoolean;
58
import java.util.logging.Level;
53
import java.util.logging.Level;
59
import java.util.logging.Logger;
54
import java.util.logging.Logger;
60
import javax.lang.model.element.Element;
55
import javax.lang.model.element.Element;
Lines 66-188 Link Here
66
import javax.lang.model.type.TypeKind;
61
import javax.lang.model.type.TypeKind;
67
import javax.lang.model.type.TypeMirror;
62
import javax.lang.model.type.TypeMirror;
68
import javax.lang.model.util.ElementFilter;
63
import javax.lang.model.util.ElementFilter;
69
import javax.swing.text.BadLocationException;
70
import javax.swing.text.Position;
71
import javax.swing.text.StyledDocument;
72
import org.netbeans.api.java.classpath.ClassPath;
73
import org.netbeans.api.java.classpath.ClassPath.Entry;
74
import org.netbeans.api.java.queries.SourceForBinaryQuery;
75
import org.netbeans.api.java.source.CancellableTask;
76
import org.netbeans.api.java.source.Task;
77
import org.netbeans.api.java.source.ClassIndex.SearchKind;
78
import org.netbeans.api.java.source.ClasspathInfo;
79
import org.netbeans.api.java.source.CompilationController;
80
import org.netbeans.api.java.source.CompilationInfo;
64
import org.netbeans.api.java.source.CompilationInfo;
81
import org.netbeans.api.java.source.ElementHandle;
65
import org.netbeans.api.java.source.ElementHandle;
82
import org.netbeans.api.java.source.JavaSource;
83
import org.netbeans.api.java.source.SourceUtils;
66
import org.netbeans.api.java.source.SourceUtils;
84
import org.netbeans.api.java.source.ClassIndex;
85
import org.netbeans.spi.java.classpath.support.ClassPathSupport;
86
import org.openide.filesystems.FileObject;
87
import org.openide.filesystems.FileUtil;
88
import org.openide.text.NbDocument;
89
import org.openide.util.Exceptions;
90
import org.openide.util.NbBundle;
91
import org.openide.util.RequestProcessor;
92
import org.openide.util.TopologicalSortException;
93
import org.openide.util.Utilities;
94
67
95
68
96
/**
69
/**
97
 *
70
 *
98
 * @author Jan Lahoda
71
 * @author Jan Lahoda
99
 */
72
 */
100
public class IsOverriddenAnnotationHandler implements CancellableTask<CompilationInfo> {
73
public class ComputeOverriding {
101
    
74
    
102
    private static final boolean enableReverseLookups = Boolean.getBoolean("org.netbeans.java.editor.enableReverseLookups");
75
    static final Logger LOG = Logger.getLogger(ComputeOverriding.class.getName());
103
    static final Logger LOG = Logger.getLogger(IsOverriddenAnnotationHandler.class.getName());
104
76
105
    private FileObject file;
77
    private final AtomicBoolean cancel;
106
    
78
    
107
    public IsOverriddenAnnotationHandler(FileObject file) {
79
    public ComputeOverriding(AtomicBoolean cancel) {
108
        this.file = file;
80
        this.cancel = cancel;
109
        Logger.getLogger("TIMER").log(Level.FINE, "IsOverriddenAnnotationHandler", new Object[] {file, this}); //NOI18N
110
    }
111
    
112
    private IsOverriddenVisitor visitor;
113
    
114
    public void run(CompilationInfo info) throws IOException {
115
        resume();
116
        
117
        StyledDocument doc = (StyledDocument) info.getDocument();
118
        
119
        if (doc == null) {
120
            LOG.log(Level.FINE, "Cannot get document!"); //NOI18N
121
            return ;
122
        }
123
        
124
        long startTime = System.currentTimeMillis();
125
        
126
        try {
127
            List<IsOverriddenAnnotation> annotations = process(info, doc);
128
            
129
            if (annotations == null) {
130
                //cancelled:
131
                return ;
132
            }
133
            
134
            newAnnotations(annotations);
135
        } finally {
136
            synchronized (this) {
137
                visitor = null;
138
            }
139
            
140
            Logger.getLogger("TIMER").log(Level.FINE, "Overridden in", //NOI18N
141
                    new Object[] {file, System.currentTimeMillis() - startTime});
142
        }
143
    }
144
    
145
    private FileObject findSourceRoot() {
146
        final ClassPath cp = ClassPath.getClassPath(file, ClassPath.SOURCE);
147
        if (cp != null) {
148
            for (FileObject root : cp.getRoots()) {
149
                if (FileUtil.isParentOf(root, file))
150
                    return root;
151
            }
152
        }
153
        //Null is a valid value for files which have no source path (default filesystem).
154
        return null;
155
    }
156
    
157
    //temporary hack:
158
    private synchronized Set<FileObject> findReverseSourceRoots(final FileObject thisSourceRoot, final FileObject thisFile) {
159
        final Object o = new Object();
160
        final Set<FileObject> reverseSourceRoots = new HashSet<FileObject>();
161
        
162
        RequestProcessor.getDefault().post(new Runnable() {
163
            public void run() {
164
                long startTime = System.currentTimeMillis();
165
                Set<FileObject> reverseSourceRootsInt = new HashSet<FileObject>(ReverseSourceRootsLookup.reverseSourceRootsLookup(thisSourceRoot));
166
                long endTime = System.currentTimeMillis();
167
                
168
                Logger.getLogger("TIMER").log(Level.FINE, "Find Reverse Source Roots", //NOI18N
169
                    new Object[] {thisFile, endTime - startTime});
170
                
171
                synchronized (o) {
172
                    reverseSourceRoots.addAll(reverseSourceRootsInt);
173
                }
174
                
175
                wakeUp();
176
            }
177
        });
178
        
179
        try {
180
            wait();
181
        } catch (InterruptedException ex) {
182
            Exceptions.printStackTrace(ex);
183
        }
184
        
185
        return reverseSourceRoots;
186
    }
81
    }
187
    
82
    
188
    public static AnnotationType detectOverrides(CompilationInfo info, TypeElement type, ExecutableElement ee, List<ElementDescription> result) {
83
    public static AnnotationType detectOverrides(CompilationInfo info, TypeElement type, ExecutableElement ee, List<ElementDescription> result) {
Lines 201-207 Link Here
201
        for (ExecutableElement overridee : lee) {
96
        for (ExecutableElement overridee : lee) {
202
            if (info.getElements().overrides(ee, overridee, SourceUtils.getEnclosingTypeElement(ee))) {
97
            if (info.getElements().overrides(ee, overridee, SourceUtils.getEnclosingTypeElement(ee))) {
203
                if (seenMethods.add(overridee)) {
98
                if (seenMethods.add(overridee)) {
204
                    result.add(new ElementDescription(info, overridee));
99
                    result.add(new ElementDescription(info, overridee, false));
205
                }
100
                }
206
            }
101
            }
207
        }
102
        }
Lines 219-234 Link Here
219
        return null;
114
        return null;
220
    }
115
    }
221
    
116
    
222
    public List<IsOverriddenAnnotation> process(CompilationInfo info, final StyledDocument doc) {
117
    public Map<ElementHandle<? extends Element>, List<ElementDescription>> process(CompilationInfo info) {
223
        IsOverriddenVisitor v;
118
        IsOverriddenVisitor v = new IsOverriddenVisitor(info, cancel);
224
        
225
        synchronized (this) {
226
            if (isCanceled())
227
                return null;
228
            
229
            v = visitor = new IsOverriddenVisitor(doc, info);
230
        }
231
        
232
        CompilationUnitTree unit = info.getCompilationUnit();
119
        CompilationUnitTree unit = info.getCompilationUnit();
233
        
120
        
234
        long startTime1 = System.currentTimeMillis();
121
        long startTime1 = System.currentTimeMillis();
Lines 238-264 Link Here
238
        long endTime1 = System.currentTimeMillis();
125
        long endTime1 = System.currentTimeMillis();
239
        
126
        
240
        Logger.getLogger("TIMER").log(Level.FINE, "Overridden Scanner", //NOI18N
127
        Logger.getLogger("TIMER").log(Level.FINE, "Overridden Scanner", //NOI18N
241
                    new Object[] {file, endTime1 - startTime1});
128
                    new Object[] {info.getFileObject(), endTime1 - startTime1});
242
        
129
        
243
        Set<FileObject> reverseSourceRoots;
130
        Map<ElementHandle<? extends Element>, List<ElementDescription>> result = new HashMap<ElementHandle<? extends Element>, List<ElementDescription>>();
244
        
245
        if (enableReverseLookups) {
246
            FileObject thisSourceRoot = findSourceRoot();
247
            if (thisSourceRoot == null) {
248
                return null;
249
            }
250
            
251
            reverseSourceRoots = findReverseSourceRoots(thisSourceRoot, info.getFileObject());
252
            
253
            //XXX: special case "this" source root (no need to create a new JS and load the classes again for it):
254
            reverseSourceRoots.add(thisSourceRoot);
255
        } else {
256
            reverseSourceRoots = null;
257
        }
258
        
259
        LOG.log(Level.FINE, "reverseSourceRoots: {0}", reverseSourceRoots); //NOI18N
260
        
261
        List<IsOverriddenAnnotation> annotations = new ArrayList<IsOverriddenAnnotation>();
262
        
131
        
263
        for (ElementHandle<TypeElement> td : v.type2Declaration.keySet()) {
132
        for (ElementHandle<TypeElement> td : v.type2Declaration.keySet()) {
264
            if (isCanceled())
133
            if (isCanceled())
Lines 295-624 Link Here
295
                }
164
                }
296
                
165
                
297
                Set<ExecutableElement> seenMethods = new HashSet<ExecutableElement>();
166
                Set<ExecutableElement> seenMethods = new HashSet<ExecutableElement>();
298
                List<ElementDescription> overrides = new ArrayList<ElementDescription>();
167
                List<ElementDescription> descriptions = new LinkedList<ElementDescription>();
299
                
168
300
                for (ExecutableElement overridee : lee) {
169
                for (ExecutableElement overridee : lee) {
301
                    if (info.getElements().overrides(ee, overridee, SourceUtils.getEnclosingTypeElement(ee))) {
170
                    if (info.getElements().overrides(ee, overridee, SourceUtils.getEnclosingTypeElement(ee))) {
302
                        if (seenMethods.add(overridee)) {
171
                        if (seenMethods.add(overridee)) {
303
                            overrides.add(new ElementDescription(info, overridee));
172
                            descriptions.add(new ElementDescription(info, overridee, false));
304
                        }
173
                        }
305
                    }
174
                    }
306
                }
175
                }
307
                
176
308
                if (!overrides.isEmpty()) {
177
                result.put(methodHandle, descriptions);
309
                    int position = (int) info.getTrees().getSourcePositions().getStartPosition(info.getCompilationUnit(), v.declaration2Tree.get(methodHandle));
310
                    Position pos = getPosition(doc, position);
311
                    
312
                    if (pos == null) {
313
                        //cannot compute the position, skip
314
                        continue;
315
                    }
316
                    
317
                    StringBuffer tooltip = new StringBuffer();
318
                    boolean wasOverrides = false;
319
                    
320
                    boolean newline = false;
321
                    
322
                    for (ElementDescription ed : overrides) {
323
                        if (newline) {
324
                            tooltip.append("\n"); //NOI18N
325
                        }
326
                        
327
                        newline = true;
328
                        
329
                        if (ed.getModifiers().contains(Modifier.ABSTRACT)) {
330
                            tooltip.append(NbBundle.getMessage(IsOverriddenAnnotationHandler.class, "TP_Implements", ed.getDisplayName()));
331
                        } else {
332
                            tooltip.append(NbBundle.getMessage(IsOverriddenAnnotationHandler.class, "TP_Overrides", ed.getDisplayName()));
333
                            wasOverrides = true;
334
                        }
335
                    }
336
                    
337
                    annotations.add(new IsOverriddenAnnotation(doc, pos, wasOverrides ? AnnotationType.OVERRIDES : AnnotationType.IMPLEMENTS, tooltip.toString(), overrides));
338
                }
339
            }
340
            
341
            if (enableReverseLookups) {
342
                String typeOverridden = null;
343
                AnnotationType typeType = null;
344
                TypeElement resolved = td.resolve(info);
345
                
346
                
347
                if (resolved == null) {
348
                    Logger.getLogger("global").log(Level.SEVERE, "IsOverriddenAnnotationHandler: resolved == null!"); //NOI18N
349
                    continue;
350
                }
351
                
352
                if (resolved.getKind().isInterface()) {
353
                    typeOverridden = NbBundle.getMessage(IsOverriddenAnnotationHandler.class, "CAP_HasImplementations");
354
                    typeType = AnnotationType.HAS_IMPLEMENTATION;
355
                }
356
                
357
                if (resolved.getKind().isClass()) {
358
                    typeOverridden = NbBundle.getMessage(IsOverriddenAnnotationHandler.class, "CAP_IsOverridden");
359
                    typeType = AnnotationType.IS_OVERRIDDEN;
360
                }
361
                
362
                final Map<ElementHandle<ExecutableElement>, List<ElementDescription>> overriding = new HashMap<ElementHandle<ExecutableElement>, List<ElementDescription>>();
363
                final List<ElementDescription> overridingClasses = new ArrayList<ElementDescription>();
364
                
365
                long startTime = System.currentTimeMillis();
366
                long[] classIndexTime = new long[1];
367
                final Map<FileObject, Set<ElementHandle<TypeElement>>> users = computeUsers(reverseSourceRoots, ElementHandle.create(resolved), classIndexTime);
368
                long endTime = System.currentTimeMillis();
369
                
370
                if (users == null) {
371
                    return null;
372
                }
373
                
374
                Logger.getLogger("TIMER").log(Level.FINE, "Overridden Users Class Index", //NOI18N
375
                    new Object[] {file, classIndexTime[0]});
376
                Logger.getLogger("TIMER").log(Level.FINE, "Overridden Users", //NOI18N
377
                    new Object[] {file, endTime - startTime});
378
                
379
                for (Map.Entry<FileObject, Set<ElementHandle<TypeElement>>> data : users.entrySet()) {
380
                    if (isCanceled())
381
                        return null;
382
                    
383
                    findOverriddenAnnotations(data.getKey(), data.getValue(), td, v.type2Declaration.get(td), overriding, overridingClasses);
384
                }
385
                
386
                if (!overridingClasses.isEmpty()) {
387
                    Tree t = v.declaration2Class.get(td);
388
                    
389
                    if (t != null) {
390
                        Position pos = getPosition(doc, (int) info.getTrees().getSourcePositions().getStartPosition(unit, t));
391
                        
392
                        if (pos == null) {
393
                            //cannot compute the position, skip
394
                            continue;
395
                        }
396
                        
397
                        annotations.add(new IsOverriddenAnnotation(doc, pos, typeType, typeOverridden.toString(), overridingClasses));
398
                    }
399
                }
400
                
401
                for (ElementHandle<ExecutableElement> original : overriding.keySet()) {
402
                    if (isCanceled())
403
                        return null;
404
                    
405
                    Position pos = getPosition(doc, (int) info.getTrees().getSourcePositions().getStartPosition(unit, v.declaration2Tree.get(original)));
406
                    
407
                    if (pos == null) {
408
                        //cannot compute the position, skip
409
                        continue;
410
                    }
411
                    
412
                    Set<Modifier> mods = original.resolve(info).getModifiers();
413
                    String tooltip = null;
414
                    
415
                    if (mods.contains(Modifier.ABSTRACT)) {
416
                        tooltip = NbBundle.getMessage(IsOverriddenAnnotationHandler.class, "TP_HasImplementations");
417
                    } else {
418
                        tooltip = NbBundle.getMessage(IsOverriddenAnnotationHandler.class, "TP_IsOverridden");
419
                    }
420
                    
421
                    IsOverriddenAnnotation ann = new IsOverriddenAnnotation(doc, pos, mods.contains(Modifier.ABSTRACT) ? AnnotationType.HAS_IMPLEMENTATION : AnnotationType.IS_OVERRIDDEN, tooltip, overriding.get(original));
422
                    
423
                    annotations.add(ann);
424
                }
425
            }
178
            }
426
        }
179
        }
427
        
180
        
428
        if (isCanceled())
181
        if (isCanceled())
429
            return null;
182
            return null;
430
        else
183
        else
431
            return annotations;
432
    }
433
    
434
    private static final ClassPath EMPTY = ClassPathSupport.createClassPath(new URL[0]);
435
    
436
    private Set<ElementHandle<TypeElement>> computeUsers(FileObject source, Set<ElementHandle<TypeElement>> base, long[] classIndexCumulative) {
437
        ClasspathInfo cpinfo = ClasspathInfo.create(/*source);/*/EMPTY, EMPTY, ClassPathSupport.createClassPath(new FileObject[] {source}));
438
        
439
        long startTime = System.currentTimeMillis();
440
        
441
        try {
442
            List<ElementHandle<TypeElement>> l = new LinkedList<ElementHandle<TypeElement>>(base);
443
            Set<ElementHandle<TypeElement>> result = new HashSet<ElementHandle<TypeElement>>();
444
            
445
            while (!l.isEmpty()) {
446
                ElementHandle<TypeElement> eh = l.remove(0);
447
                
448
                result.add(eh);
449
                Set<ElementHandle<TypeElement>> typeElements = cpinfo.getClassIndex().getElements(eh, Collections.singleton(SearchKind.IMPLEMENTORS), EnumSet.of(ClassIndex.SearchScope.SOURCE));
450
                //XXX: Canceling
451
                if (typeElements != null) {
452
                    l.addAll(typeElements);
453
                }
454
            }
455
            return result;
184
            return result;
456
        } finally {
457
            classIndexCumulative[0] += (System.currentTimeMillis() - startTime);
458
        }
459
    }
460
    
461
    private Map<FileObject, Set<ElementHandle<TypeElement>>> computeUsers(Set<FileObject> sources, ElementHandle<TypeElement> base, long[] classIndexCumulative) {
462
        Map<FileObject, Collection<FileObject>> edges = new HashMap<FileObject, Collection<FileObject>>();
463
        Map<FileObject, Collection<FileObject>> dependsOn = new HashMap<FileObject, Collection<FileObject>>();
464
        
465
        for (FileObject source : sources) {
466
            edges.put(source, new ArrayList<FileObject>());
467
        }
468
        
469
        for (FileObject source : sources) {
470
            List<FileObject> deps = new ArrayList<FileObject>();
471
            
472
            dependsOn.put(source, deps);
473
            
474
            for (Entry entry : ClassPath.getClassPath(source, ClassPath.COMPILE).entries()) { //TODO: should also check BOOT?
475
                for (FileObject s : SourceForBinaryQuery.findSourceRoots(entry.getURL()).getRoots()) {
476
                    Collection<FileObject> targets = edges.get(s);
477
                    
478
                    if (targets != null) {
479
                        targets.add(source);
480
                    }
481
                    
482
                    deps.add(s);
483
                }
484
            }
485
        }
486
        
487
        List<FileObject> sourceRoots = new ArrayList<FileObject>(sources);
488
        
489
        try {
490
            Utilities.topologicalSort(sourceRoots, edges);
491
        } catch (TopologicalSortException ex) {
492
            LOG.log(Level.WARNING, "internal error", ex); //NOI18N
493
            return null;
494
        }
495
        
496
        Map<FileObject, Set<ElementHandle<TypeElement>>> result = new HashMap<FileObject, Set<ElementHandle<TypeElement>>>();
497
        
498
        for (FileObject file : sourceRoots) {
499
            Set<ElementHandle<TypeElement>> baseTypes = new HashSet<ElementHandle<TypeElement>>();
500
            
501
            baseTypes.add(base);
502
            
503
            for (FileObject dep : dependsOn.get(file)) {
504
                Set<ElementHandle<TypeElement>> depTypes = result.get(dep);
505
                
506
                if (depTypes != null) {
507
                    baseTypes.addAll(depTypes);
508
                }
509
            }
510
            
511
            Set<ElementHandle<TypeElement>> types = computeUsers(file, baseTypes, classIndexCumulative);
512
            
513
            types.removeAll(baseTypes);
514
            
515
            result.put(file, types);
516
        }
517
        
518
        return result;
519
    }
520
    private void findOverriddenAnnotations(
521
            FileObject sourceRoot,
522
            final Set<ElementHandle<TypeElement>> users,
523
            final ElementHandle<TypeElement> originalType,
524
            final List<ElementHandle<ExecutableElement>> methods,
525
            final Map<ElementHandle<ExecutableElement>, List<ElementDescription>> overriding,
526
            final List<ElementDescription> overridingClasses) {
527
        ClasspathInfo cpinfo = ClasspathInfo.create(sourceRoot);
528
        
529
        if (!users.isEmpty()) {
530
            JavaSource js = JavaSource.create(cpinfo);
531
            
532
            try {
533
                js.runUserActionTask(new Task<CompilationController>() {
534
535
                    public void run(CompilationController controller) throws Exception {
536
                        Set<Element> seenElements = new HashSet<Element>();
537
                        
538
                        for (ElementHandle<TypeElement> typeHandle : users) {
539
                            if (isCanceled())
540
                                return;
541
                            TypeElement type = typeHandle.resolve(controller);
542
                            Element resolvedOriginalType = originalType.resolve(controller);
543
                            
544
                            if (!seenElements.add(resolvedOriginalType))
545
                                continue;
546
                            
547
                            if (controller.getTypes().isSubtype(type.asType(), resolvedOriginalType.asType())) {
548
                                overridingClasses.add(new ElementDescription(controller, type));
549
                                
550
                                for (ElementHandle<ExecutableElement> originalMethodHandle : methods) {
551
                                    ExecutableElement originalMethod = originalMethodHandle.resolve(controller);
552
                                    
553
                                    if (originalMethod != null) {
554
                                        ExecutableElement overrider = getImplementationOf(controller, originalMethod, type);
555
                                        
556
                                        if (overrider == null)
557
                                            continue;
558
                                        
559
                                        List<ElementDescription> overriddingMethods = overriding.get(originalMethodHandle);
560
                                        
561
                                        if (overriddingMethods == null) {
562
                                            overriding.put(originalMethodHandle, overriddingMethods = new ArrayList<ElementDescription>());
563
                                        }
564
                                        
565
                                        overriddingMethods.add(new ElementDescription(controller, overrider));
566
                                    } else {
567
                                        Logger.getLogger("global").log(Level.SEVERE, "IsOverriddenAnnotationHandler: originalMethod == null!"); //NOI18N
568
                                    }
569
                                }
570
                            }
571
                        }
572
                    }
573
                },true);
574
            } catch (Exception e) {
575
                Exceptions.printStackTrace(e);
576
            }
577
        }
578
    }
579
    
580
    private ExecutableElement getImplementationOf(CompilationInfo info, ExecutableElement overridee, TypeElement implementor) {
581
        for (ExecutableElement overrider : ElementFilter.methodsIn(implementor.getEnclosedElements())) {
582
            if (info.getElements().overrides(overrider, overridee, implementor)) {
583
                return overrider;
584
            }
585
        }
586
        
587
        return null;
588
    }
589
            
590
    private boolean canceled;
591
    
592
    public synchronized void cancel() {
593
        canceled = true;
594
        
595
        if (visitor != null) {
596
            visitor.cancel();
597
        }
598
        
599
        wakeUp();
600
    }
601
    
602
    private synchronized void resume() {
603
        canceled = false;
604
    }
605
    
606
    private synchronized void wakeUp() {
607
        notifyAll();
608
    }
185
    }
609
    
186
    
610
    private synchronized boolean isCanceled() {
187
    private synchronized boolean isCanceled() {
611
        return canceled;
188
        return cancel.get();
612
    }
189
    }
613
    
190
    
614
    private void newAnnotations(List<IsOverriddenAnnotation> as) {
615
        AnnotationsHolder a = AnnotationsHolder.get(file);
616
        
617
        if (a != null) {
618
            a.setNewAnnotations(as);
619
        }
620
    }
621
622
    private static void sortOutMethods(CompilationInfo info, Map<Name, List<ExecutableElement>> where, Element td, boolean current) {
191
    private static void sortOutMethods(CompilationInfo info, Map<Name, List<ExecutableElement>> where, Element td, boolean current) {
623
        if (current) {
192
        if (current) {
624
            Map<Name, List<ExecutableElement>> newlyAdded = new HashMap<Name, List<ExecutableElement>>();
193
            Map<Name, List<ExecutableElement>> newlyAdded = new HashMap<Name, List<ExecutableElement>>();
Lines 662-688 Link Here
662
        }
231
        }
663
    }
232
    }
664
    
233
    
665
    private static Position getPosition(final StyledDocument doc, final int offset) {
666
        class Impl implements Runnable {
667
            private Position pos;
668
            public void run() {
669
                if (offset < 0 || offset >= doc.getLength())
670
                    return ;
671
                
672
                try {
673
                    pos = doc.createPosition(offset - NbDocument.findLineColumn(doc, offset));
674
                } catch (BadLocationException ex) {
675
                    //should not happen?
676
                    LOG.log(Level.FINE, null, ex);
677
                }
678
            }
679
        }
680
        
681
        Impl i = new Impl();
682
        
683
        doc.render(i);
684
        
685
        return i.pos;
686
    }
687
    
688
}
234
}
(-)a/java.editor/src/org/netbeans/modules/java/editor/overridden/ElementDescription.java (-4 / +18 lines)
Lines 40-45 Link Here
40
 */
40
 */
41
package org.netbeans.modules.java.editor.overridden;
41
package org.netbeans.modules.java.editor.overridden;
42
42
43
import java.awt.Image;
43
import java.util.Collection;
44
import java.util.Collection;
44
import javax.lang.model.element.Element;
45
import javax.lang.model.element.Element;
45
import javax.lang.model.element.ExecutableElement;
46
import javax.lang.model.element.ExecutableElement;
Lines 57-62 Link Here
57
import org.netbeans.api.java.source.ui.ElementIcons;
58
import org.netbeans.api.java.source.ui.ElementIcons;
58
import org.netbeans.modules.editor.java.Utilities;
59
import org.netbeans.modules.editor.java.Utilities;
59
import org.openide.filesystems.FileObject;
60
import org.openide.filesystems.FileObject;
61
import org.openide.util.ImageUtilities;
60
import org.openide.util.NbBundle;
62
import org.openide.util.NbBundle;
61
63
62
/**
64
/**
Lines 71-83 Link Here
71
    private ElementHandle<TypeElement> outtermostElement;
73
    private ElementHandle<TypeElement> outtermostElement;
72
    private Collection<Modifier> modifiers;
74
    private Collection<Modifier> modifiers;
73
    private String displayName;
75
    private String displayName;
74
    
76
    private final boolean overriddenFlag;
75
    public ElementDescription(CompilationInfo info, Element element) {
77
78
    public ElementDescription(CompilationInfo info, Element element, boolean overriddenFlag) {
76
        this.originalCPInfo = info.getClasspathInfo();
79
        this.originalCPInfo = info.getClasspathInfo();
77
        this.handle = ElementHandle.create(element);
80
        this.handle = ElementHandle.create(element);
78
        this.outtermostElement = ElementHandle.create(SourceUtils.getOutermostEnclosingTypeElement(element));
81
        this.outtermostElement = ElementHandle.create(SourceUtils.getOutermostEnclosingTypeElement(element));
79
        this.modifiers = element.getModifiers();
82
        this.modifiers = element.getModifiers();
80
        this.displayName = element.accept(new ElementNameVisitor(), true);
83
        this.displayName = element.accept(new ElementNameVisitor(), true);
84
        this.overriddenFlag = overriddenFlag;
81
    }
85
    }
82
86
83
    public FileObject getSourceFile() {
87
    public FileObject getSourceFile() {
Lines 93-101 Link Here
93
    }
97
    }
94
98
95
    public Icon getIcon() {
99
    public Icon getIcon() {
96
        return ElementIcons.getElementIcon(handle.getKind(), modifiers);
100
        Image badge;
101
102
        if (overriddenFlag) {
103
            badge = ImageUtilities.loadImage("org/netbeans/modules/java/editor/resources/is-overridden-badge.png");
104
        } else {
105
            badge = ImageUtilities.loadImage("org/netbeans/modules/java/editor/resources/overrides-badge.png");
106
        }
107
108
        Image icon = ImageUtilities.icon2Image(ElementIcons.getElementIcon(handle.getKind(), modifiers));
109
110
        return ImageUtilities.image2Icon(ImageUtilities.mergeImages(icon, badge, 16, 0));
97
    }
111
    }
98
    
112
99
    public String getDisplayName() {
113
    public String getDisplayName() {
100
        return displayName;
114
        return displayName;
101
    }
115
    }
(-)a/java.editor/src/org/netbeans/modules/java/editor/overridden/GoToImplementation.java (+212 lines)
Line 0 Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2008-2009 Sun Microsystems, Inc. All rights reserved.
5
 *
6
 * The contents of this file are subject to the terms of either the GNU
7
 * General Public License Version 2 only ("GPL") or the Common
8
 * Development and Distribution License("CDDL") (collectively, the
9
 * "License"). You may not use this file except in compliance with the
10
 * License. You can obtain a copy of the License at
11
 * http://www.netbeans.org/cddl-gplv2.html
12
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
13
 * specific language governing permissions and limitations under the
14
 * License.  When distributing the software, include this License Header
15
 * Notice in each file and include the License file at
16
 * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
17
 * particular file as subject to the "Classpath" exception as provided
18
 * by Sun in the GPL Version 2 section of the License file that
19
 * accompanied this code. If applicable, add the following below the
20
 * License Header, with the fields enclosed by brackets [] replaced by
21
 * your own identifying information:
22
 * "Portions Copyrighted [year] [name of copyright owner]"
23
 *
24
 * If you wish your version of this file to be governed by only the CDDL
25
 * or only the GPL Version 2, indicate your decision by adding
26
 * "[Contributor] elects to include this software in this distribution
27
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
28
 * single choice of license, a recipient has the option to distribute
29
 * your version of this file under either the CDDL, the GPL Version 2 or
30
 * to extend the choice of license to its licensees as provided above.
31
 * However, if you add GPL Version 2 code and therefore, elected the GPL
32
 * Version 2 license, then the option applies only if the new code is
33
 * made subject to such option by the copyright holder.
34
 *
35
 * Contributor(s):
36
 *
37
 * Portions Copyrighted 2008-2009 Sun Microsystems, Inc.
38
 */
39
package org.netbeans.modules.java.editor.overridden;
40
41
import com.sun.source.tree.BlockTree;
42
import com.sun.source.tree.MethodTree;
43
import com.sun.source.tree.Tree.Kind;
44
import com.sun.source.util.SourcePositions;
45
import com.sun.source.util.TreePath;
46
import java.awt.Point;
47
import java.awt.event.ActionEvent;
48
import java.io.IOException;
49
import java.util.EnumSet;
50
import java.util.List;
51
import java.util.Map;
52
import java.util.Set;
53
import java.util.concurrent.atomic.AtomicBoolean;
54
import javax.lang.model.element.Element;
55
import javax.lang.model.element.ElementKind;
56
import javax.lang.model.element.ExecutableElement;
57
import javax.lang.model.element.TypeElement;
58
import javax.swing.SwingUtilities;
59
import javax.swing.text.Document;
60
import javax.swing.text.JTextComponent;
61
import org.netbeans.api.editor.EditorActionRegistration;
62
import org.netbeans.api.java.lexer.JavaTokenId;
63
import org.netbeans.api.java.source.CompilationController;
64
import org.netbeans.api.java.source.CompilationInfo;
65
import org.netbeans.api.java.source.ElementHandle;
66
import org.netbeans.api.java.source.JavaSource;
67
import org.netbeans.api.java.source.JavaSource.Phase;
68
import org.netbeans.api.java.source.Task;
69
import org.netbeans.api.lexer.TokenSequence;
70
import org.netbeans.editor.BaseAction;
71
import org.netbeans.editor.ext.ExtKit;
72
import org.netbeans.modules.editor.java.JavaKit;
73
import org.netbeans.modules.java.editor.semantic.Utilities;
74
import org.openide.awt.StatusDisplayer;
75
import org.openide.util.Exceptions;
76
import org.openide.util.NbBundle;
77
78
@EditorActionRegistration(
79
        name = "goto-implementation",
80
        mimeType = JavaKit.JAVA_MIME_TYPE,
81
        popupText = "#CTL_GoToImplementation"
82
)
83
public final class GoToImplementation extends BaseAction {
84
85
    public GoToImplementation() {
86
        super(SAVE_POSITION | ABBREV_RESET);
87
//        putValue(SHORT_DESCRIPTION, NbBundle.getMessage(GoToImplementation.class, "CTL_GoToImplementation"));
88
//        String name = NbBundle.getMessage(GoToImplementation.class, "CTL_GoToImplementation_trimmed");
89
//        putValue(ExtKit.TRIMMED_TEXT,name);
90
//        putValue(POPUP_MENU_TEXT, name);
91
    }
92
93
    public void actionPerformed(ActionEvent e, final JTextComponent c) {
94
        try {
95
            JavaSource.forDocument(c.getDocument()).runUserActionTask(new Task<CompilationController>() {
96
                public void run(CompilationController parameter) throws Exception {
97
                    parameter.toPhase(Phase.RESOLVED);
98
                    
99
                    Element el = resolveElement(parameter, c.getCaretPosition());
100
101
                    if (el == null) {
102
                        StatusDisplayer.getDefault().setStatusText(NbBundle.getMessage(GoToImplementation.class, "LBL_NoMethod"));
103
                        return ;
104
                    }
105
106
                    TypeElement type = el.getKind() == ElementKind.METHOD ? (TypeElement) el.getEnclosingElement() : (TypeElement) el;
107
                    ExecutableElement method = el.getKind() == ElementKind.METHOD ? (ExecutableElement) el : null;
108
109
                    Map<ElementHandle<? extends Element>, List<ElementDescription>> overriding = new ComputeOverriders(new AtomicBoolean()).process(parameter, type, method, true);
110
111
                    List<ElementDescription> overridingMethods = overriding.get(ElementHandle.create(el));
112
113
                    if (overridingMethods == null || overridingMethods.isEmpty()) {
114
                        String key = el.getKind() == ElementKind.METHOD ? "LBL_NoOverridingMethod" : "LBL_NoOverridingType";
115
116
                        StatusDisplayer.getDefault().setStatusText(NbBundle.getMessage(GoToImplementation.class, key));
117
                        return;
118
                    }
119
                    
120
                    Point p = new Point(c.modelToView(c.getCaretPosition()).getLocation());
121
122
                    SwingUtilities.convertPointToScreen(p, c);
123
                    
124
                    performGoToAction(overridingMethods, p);
125
                }
126
            }, true);
127
        } catch (IOException ex) {
128
            Exceptions.printStackTrace(ex);
129
        }
130
    }
131
132
    static void performGoToAction(List<ElementDescription> declarations, Point position) {
133
        String caption = NbBundle.getMessage(GoToImplementation.class, "LBL_ImplementorsOverriders");
134
        
135
        PopupUtil.showPopup(new IsOverriddenPopup(caption, declarations), caption, position.x, position.y, true, 0);
136
    }
137
138
    private static Set<ElementKind> SUPPORTED_ELEMENTS = EnumSet.of(ElementKind.METHOD, ElementKind.ANNOTATION_TYPE, ElementKind.CLASS, ElementKind.ENUM, ElementKind.INTERFACE);
139
    
140
    private static Element resolveElement(CompilationInfo info, int caret) {
141
        TreePath tp = info.getTreeUtilities().pathFor(caret);
142
143
        TokenSequence<JavaTokenId> ts = info.getTokenHierarchy().tokenSequence(JavaTokenId.language());
144
145
        ts.move(caret);
146
147
        boolean isIdentifier = ts.moveNext() && ts.token().id() == JavaTokenId.IDENTIFIER;
148
149
        if (!isIdentifier) {
150
            ts.move(caret);
151
            isIdentifier = ts.movePrevious() && ts.token().id() == JavaTokenId.IDENTIFIER;
152
        }
153
        
154
        if (isIdentifier) {
155
            Element  elementUnderCaret = info.getTrees().getElement(tp);
156
157
            if (elementUnderCaret != null && SUPPORTED_ELEMENTS.contains(elementUnderCaret.getKind())) {
158
                return (Element) elementUnderCaret;
159
            }
160
        }
161
162
        Element el = resolveHeader(tp, info, caret);
163
164
        if (el == null) {
165
            tp = info.getTreeUtilities().pathFor(caret + 1);
166
            el = resolveHeader(tp, info, caret);
167
        }
168
169
        return el;
170
    }
171
    
172
    private static Element resolveHeader(TreePath tp, CompilationInfo info, int caret) {
173
        while (tp.getLeaf().getKind() != Kind.METHOD && tp.getLeaf().getKind() != Kind.CLASS && tp.getLeaf().getKind() != Kind.COMPILATION_UNIT) {
174
            tp = tp.getParentPath();
175
        }
176
177
        if (tp.getLeaf().getKind() == Kind.COMPILATION_UNIT) {
178
            return null;
179
        }
180
181
        long bodyStart;
182
183
        if (tp.getLeaf().getKind() == Kind.METHOD) {
184
            MethodTree mt = (MethodTree) tp.getLeaf();
185
            SourcePositions sp = info.getTrees().getSourcePositions();
186
            BlockTree body = mt.getBody();
187
            bodyStart = body != null ? sp.getStartPosition(info.getCompilationUnit(), body) : Integer.MAX_VALUE;
188
        } else {
189
            assert tp.getLeaf().getKind() == Kind.CLASS;
190
            Document doc = info.getSnapshot().getSource().getDocument(false);
191
192
            if (doc == null) {
193
                return null;
194
            }
195
196
            bodyStart = Utilities.findBodyStart(tp.getLeaf(), info.getCompilationUnit(), info.getTrees().getSourcePositions(), doc);
197
        }
198
199
        if (caret >= bodyStart) {
200
            return null;
201
        }
202
203
        Element el = info.getTrees().getElement(tp);
204
205
        if (el == null || !SUPPORTED_ELEMENTS.contains(el.getKind())) {
206
            return null;
207
        }
208
        
209
        return (Element) el;
210
    }
211
212
}
(-)a/java.editor/src/org/netbeans/modules/java/editor/overridden/GoToSuperTypeAction.java (-1 / +1 lines)
Lines 117-123 Link Here
117
                    
117
                    
118
                    ExecutableElement ee = (ExecutableElement) resolved;
118
                    ExecutableElement ee = (ExecutableElement) resolved;
119
                    
119
                    
120
                    type[0] = IsOverriddenAnnotationHandler.detectOverrides(parameter, (TypeElement) ee.getEnclosingElement(), ee, result);
120
                    type[0] = ComputeOverriding.detectOverrides(parameter, (TypeElement) ee.getEnclosingElement(), ee, result);
121
                }
121
                }
122
                
122
                
123
            }, true);
123
            }, true);
(-)a/java.editor/src/org/netbeans/modules/java/editor/overridden/IsOverriddenAnnotationAction.java (-12 / +130 lines)
Lines 24-30 Link Here
24
 * Contributor(s):
24
 * Contributor(s):
25
 *
25
 *
26
 * The Original Software is NetBeans. The Initial Developer of the Original
26
 * The Original Software is NetBeans. The Initial Developer of the Original
27
 * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
27
 * Software is Sun Microsystems, Inc. Portions Copyright 1997-2009 Sun
28
 * Microsystems, Inc. All Rights Reserved.
28
 * Microsystems, Inc. All Rights Reserved.
29
 *
29
 *
30
 * If you wish your version of this file to be governed by only the CDDL
30
 * If you wish your version of this file to be governed by only the CDDL
Lines 41-53 Link Here
41
package org.netbeans.modules.java.editor.overridden;
41
package org.netbeans.modules.java.editor.overridden;
42
42
43
import java.awt.Point;
43
import java.awt.Point;
44
import java.awt.Toolkit;
44
import java.awt.event.ActionEvent;
45
import java.awt.event.ActionEvent;
46
import java.util.Arrays;
47
import java.util.Collection;
48
import java.util.Collections;
49
import java.util.HashSet;
50
import java.util.LinkedHashMap;
51
import java.util.LinkedList;
52
import java.util.List;
53
import java.util.Map;
54
import java.util.Map.Entry;
55
import java.util.MissingResourceException;
56
import java.util.Set;
45
import java.util.logging.Level;
57
import java.util.logging.Level;
58
import java.util.logging.Logger;
46
import javax.swing.AbstractAction;
59
import javax.swing.AbstractAction;
47
import javax.swing.Action;
60
import javax.swing.Action;
61
import javax.swing.SwingUtilities;
48
import javax.swing.text.BadLocationException;
62
import javax.swing.text.BadLocationException;
49
import javax.swing.text.Document;
63
import javax.swing.text.Document;
50
import javax.swing.text.JTextComponent;
64
import javax.swing.text.JTextComponent;
65
import org.netbeans.api.java.source.ui.ElementOpen;
51
import org.netbeans.editor.AnnotationDesc;
66
import org.netbeans.editor.AnnotationDesc;
52
import org.netbeans.editor.Annotations;
67
import org.netbeans.editor.Annotations;
53
import org.netbeans.editor.BaseDocument;
68
import org.netbeans.editor.BaseDocument;
Lines 57-63 Link Here
57
import org.openide.ErrorManager;
72
import org.openide.ErrorManager;
58
import org.openide.filesystems.FileObject;
73
import org.openide.filesystems.FileObject;
59
import org.openide.loaders.DataObject;
74
import org.openide.loaders.DataObject;
60
import org.openide.util.Exceptions;
61
import org.openide.util.NbBundle;
75
import org.openide.util.NbBundle;
62
76
63
/**
77
/**
Lines 65-71 Link Here
65
 * @author Jan Lahoda
79
 * @author Jan Lahoda
66
 */
80
 */
67
public final class IsOverriddenAnnotationAction extends AbstractAction {
81
public final class IsOverriddenAnnotationAction extends AbstractAction {
68
    
82
69
    public IsOverriddenAnnotationAction() {
83
    public IsOverriddenAnnotationAction() {
70
        putValue(NAME, NbBundle.getMessage(IsOverriddenAnnotationAction.class,
84
        putValue(NAME, NbBundle.getMessage(IsOverriddenAnnotationAction.class,
71
                                          "CTL_IsOverriddenAnnotationAction")); //NOI18N
85
                                          "CTL_IsOverriddenAnnotationAction")); //NOI18N
Lines 119-125 Link Here
119
        AnnotationsHolder ah = AnnotationsHolder.get(file);
133
        AnnotationsHolder ah = AnnotationsHolder.get(file);
120
134
121
        if (ah == null) {
135
        if (ah == null) {
122
            IsOverriddenAnnotationHandler.LOG.log(Level.INFO, "component=" + component + " does not have attached a IsOverriddenAnnotationHandler"); //NOI18N
136
            Logger.getLogger(IsOverriddenAnnotationAction.class.getName()).log(Level.INFO, "component=" + component + " does not have attached a IsOverriddenAnnotationHandler"); //NOI18N
123
137
124
            return null;
138
            return null;
125
        }
139
        }
Lines 134-146 Link Here
134
        return null;
148
        return null;
135
    }
149
    }
136
    
150
    
151
    private List<IsOverriddenAnnotation> findAnnotations(JTextComponent component, int offset) {
152
        FileObject file = getFile(component);
153
154
        if (file == null) {
155
            if (ErrorManager.getDefault().isLoggable(ErrorManager.WARNING)) {
156
                ErrorManager.getDefault().log(ErrorManager.WARNING, "component=" + component + " does not have a file specified in the document."); //NOI18N
157
            }
158
            return null;
159
        }
160
161
        AnnotationsHolder ah = AnnotationsHolder.get(file);
162
163
        if (ah == null) {
164
            Logger.getLogger(IsOverriddenAnnotationAction.class.getName()).log(Level.INFO, "component=" + component + " does not have attached a IsOverriddenAnnotationHandler"); //NOI18N
165
166
            return null;
167
        }
168
169
        List<IsOverriddenAnnotation> annotations = new LinkedList<IsOverriddenAnnotation>();
170
171
        for(IsOverriddenAnnotation a : ah.getAnnotations()) {
172
            if (a.getPosition().getOffset() == offset) {
173
                annotations.add(a);
174
            }
175
        }
176
177
        return annotations;
178
    }
179
137
    boolean invokeDefaultAction(final JTextComponent comp) {
180
    boolean invokeDefaultAction(final JTextComponent comp) {
138
        final Document doc = comp.getDocument();
181
        final Document doc = comp.getDocument();
139
        
182
        
140
        if (doc instanceof BaseDocument) {
183
        if (doc instanceof BaseDocument) {
141
            final int currentPosition = comp.getCaretPosition();
184
            final int currentPosition = comp.getCaretPosition();
142
            final Annotations annotations = ((BaseDocument) doc).getAnnotations();
185
            final Annotations annotations = ((BaseDocument) doc).getAnnotations();
143
            final IsOverriddenAnnotation[] annotation = new IsOverriddenAnnotation[1];
186
            final Map<String, List<ElementDescription>> caption2Descriptions = new LinkedHashMap<String, List<ElementDescription>>();
144
            final Point[] p = new Point[1];
187
            final Point[] p = new Point[1];
145
            
188
            
146
            doc.render(new Runnable() {
189
            doc.render(new Runnable() {
Lines 148-173 Link Here
148
                    try {
191
                    try {
149
                        int line = Utilities.getLineOffset((BaseDocument) doc, currentPosition);
192
                        int line = Utilities.getLineOffset((BaseDocument) doc, currentPosition);
150
                        int startOffset = Utilities.getRowStartFromLineOffset((BaseDocument) doc, line);
193
                        int startOffset = Utilities.getRowStartFromLineOffset((BaseDocument) doc, line);
194
                        p[0] = comp.modelToView(startOffset).getLocation();
151
                        AnnotationDesc desc = annotations.getActiveAnnotation(line);
195
                        AnnotationDesc desc = annotations.getActiveAnnotation(line);
152
                        p[0] = comp.modelToView(startOffset).getLocation();
196
153
                        annotation[0] = findAnnotation(comp, desc, startOffset);
197
                        if (desc == null) {
198
                            return ;
199
                        }
200
                        
201
                        Collection<IsOverriddenAnnotation> annots;
202
203
                        if (COMBINED_TYPES.contains(desc.getAnnotationType())) {
204
                            annots = findAnnotations(comp, startOffset);
205
                        } else {
206
                            annots = Collections.singletonList(findAnnotation(comp, desc, startOffset));
207
                        }
208
209
                        for (IsOverriddenAnnotation a : annots) {
210
                            if (a != null) {
211
                                caption2Descriptions.put(computeCaption(a.getType(), a.getShortDescription()), a.getDeclarations());
212
                            }
213
                        }
154
                    }  catch (BadLocationException ex) {
214
                    }  catch (BadLocationException ex) {
155
                        Exceptions.printStackTrace(ex);
215
                        ErrorManager.getDefault().notify(ex);
156
                    }
216
                    }
157
                }
217
                }
158
            });
218
            });
159
            
219
            
160
            if (annotation[0] == null)
220
            if (caption2Descriptions.isEmpty())
161
                return false;
221
                return false;
162
            
222
            
163
            JumpList.checkAddEntry(comp, currentPosition);
223
            JumpList.checkAddEntry(comp, currentPosition);
164
            
224
165
            annotation[0].mouseClicked(comp, p[0]);
225
            mouseClicked(caption2Descriptions, comp, p[0]);
166
            
226
            
167
            return true;
227
            return true;
168
        }
228
        }
169
        
229
        
170
        return false;
230
        return false;
171
    }
231
    }
172
    
232
233
    private static void mouseClicked(Map<String, List<ElementDescription>> caption2Descriptions, JTextComponent c, Point p) {
234
        if (caption2Descriptions.size() == 1 && caption2Descriptions.values().iterator().next().size() == 1) {
235
            ElementDescription desc = caption2Descriptions.values().iterator().next().get(0);
236
            FileObject file = desc.getSourceFile();
237
238
            if (file != null) {
239
                ElementOpen.open(file, desc.getHandle());
240
            } else {
241
                Toolkit.getDefaultToolkit().beep();
242
            }
243
244
            return ;
245
        }
246
        
247
        Point position = new Point(p);
248
249
        SwingUtilities.convertPointToScreen(position, c);
250
251
        StringBuilder caption = new StringBuilder();
252
        List<ElementDescription> descriptions = new LinkedList<ElementDescription>();
253
        boolean first = true;
254
255
        for (Entry<String, List<ElementDescription>> e : caption2Descriptions.entrySet()) {
256
            if (!first) {
257
                caption.append("/");
258
            }
259
            first = false;
260
            caption.append(e.getKey());
261
            descriptions.addAll(e.getValue());
262
        }
263
264
        PopupUtil.showPopup(new IsOverriddenPopup(caption.toString(), descriptions), caption.toString(), position.x, position.y, true, 0);
265
    }
266
267
    private static String computeCaption(AnnotationType type, String shortDescription) throws MissingResourceException, IllegalStateException {
268
        String caption;
269
        switch (type) {
270
            case IMPLEMENTS:
271
                caption = NbBundle.getMessage(IsOverriddenAnnotation.class, "CAP_Implements");
272
                break;
273
            case OVERRIDES:
274
                caption = NbBundle.getMessage(IsOverriddenAnnotation.class, "CAP_Overrides");
275
                break;
276
            case HAS_IMPLEMENTATION:
277
            case IS_OVERRIDDEN:
278
                caption = shortDescription;
279
                break;
280
            default:
281
                throw new IllegalStateException("Currently not implemented: " + type); //NOI18N
282
        }
283
        return caption;
284
    }
285
286
    private static final Set<String> COMBINED_TYPES = new HashSet<String>(Arrays.asList(
287
            "org-netbeans-modules-editor-java-implements-has-implementations-combined",
288
            "org-netbeans-modules-editor-java-implements-is-overridden-combined",
289
            "org-netbeans-modules-editor-java-override-is-overridden-combined"
290
    ));
173
}
291
}
(-)a/java.editor/src/org/netbeans/modules/java/editor/overridden/IsOverriddenAnnotationHandlerFactory.java (-68 lines)
Lines 1-68 Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
5
 *
6
 * The contents of this file are subject to the terms of either the GNU
7
 * General Public License Version 2 only ("GPL") or the Common
8
 * Development and Distribution License("CDDL") (collectively, the
9
 * "License"). You may not use this file except in compliance with the
10
 * License. You can obtain a copy of the License at
11
 * http://www.netbeans.org/cddl-gplv2.html
12
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
13
 * specific language governing permissions and limitations under the
14
 * License.  When distributing the software, include this License Header
15
 * Notice in each file and include the License file at
16
 * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
17
 * particular file as subject to the "Classpath" exception as provided
18
 * by Sun in the GPL Version 2 section of the License file that
19
 * accompanied this code. If applicable, add the following below the
20
 * License Header, with the fields enclosed by brackets [] replaced by
21
 * your own identifying information:
22
 * "Portions Copyrighted [year] [name of copyright owner]"
23
 *
24
 * Contributor(s):
25
 *
26
 * The Original Software is NetBeans. The Initial Developer of the Original
27
 * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
28
 * Microsystems, Inc. All Rights Reserved.
29
 *
30
 * If you wish your version of this file to be governed by only the CDDL
31
 * or only the GPL Version 2, indicate your decision by adding
32
 * "[Contributor] elects to include this software in this distribution
33
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
34
 * single choice of license, a recipient has the option to distribute
35
 * your version of this file under either the CDDL, the GPL Version 2 or
36
 * to extend the choice of license to its licensees as provided above.
37
 * However, if you add GPL Version 2 code and therefore, elected the GPL
38
 * Version 2 license, then the option applies only if the new code is
39
 * made subject to such option by the copyright holder.
40
 */
41
package org.netbeans.modules.java.editor.overridden;
42
43
import org.netbeans.api.java.source.CancellableTask;
44
import org.netbeans.api.java.source.CompilationInfo;
45
import org.netbeans.api.java.source.JavaSource.Phase;
46
import org.netbeans.api.java.source.JavaSource.Priority;
47
import org.netbeans.api.java.source.support.EditorAwareJavaSourceTaskFactory;
48
import org.openide.filesystems.FileObject;
49
50
/**
51
 *
52
 * @author Jan Lahoda
53
 */
54
@org.openide.util.lookup.ServiceProvider(service=org.netbeans.api.java.source.JavaSourceTaskFactory.class)
55
public class IsOverriddenAnnotationHandlerFactory extends EditorAwareJavaSourceTaskFactory {
56
    
57
    /**
58
     * Creates a new instance of IsOverriddenAnnotationHandlerFactory
59
     */
60
    public IsOverriddenAnnotationHandlerFactory() {
61
        super(Phase.RESOLVED, Priority.MIN);
62
    }
63
64
    public CancellableTask<CompilationInfo> createTask(FileObject file) {
65
        return new IsOverriddenAnnotationHandler(file);
66
    }
67
68
}
(-)a/java.editor/src/org/netbeans/modules/java/editor/overridden/IsOverriddenVisitor.java (-5 / +3 lines)
Lines 47-62 Link Here
47
import java.util.HashMap;
47
import java.util.HashMap;
48
import java.util.List;
48
import java.util.List;
49
import java.util.Map;
49
import java.util.Map;
50
import java.util.concurrent.atomic.AtomicBoolean;
50
import javax.lang.model.element.Element;
51
import javax.lang.model.element.Element;
51
import javax.lang.model.element.ElementKind;
52
import javax.lang.model.element.ElementKind;
52
import javax.lang.model.element.ExecutableElement;
53
import javax.lang.model.element.ExecutableElement;
53
import javax.lang.model.element.Modifier;
54
import javax.lang.model.element.Modifier;
54
import javax.lang.model.element.TypeElement;
55
import javax.lang.model.element.TypeElement;
55
import javax.swing.text.Document;
56
import org.netbeans.api.java.source.CompilationInfo;
56
import org.netbeans.api.java.source.CompilationInfo;
57
import org.netbeans.api.java.source.ElementHandle;
57
import org.netbeans.api.java.source.ElementHandle;
58
import org.netbeans.api.java.source.support.CancellableTreePathScanner;
58
import org.netbeans.api.java.source.support.CancellableTreePathScanner;
59
import org.netbeans.api.java.source.ClassIndex;
60
59
61
/**
60
/**
62
 *
61
 *
Lines 65-71 Link Here
65
class IsOverriddenVisitor extends CancellableTreePathScanner<Void, Tree> {
64
class IsOverriddenVisitor extends CancellableTreePathScanner<Void, Tree> {
66
    
65
    
67
    private CompilationInfo info;
66
    private CompilationInfo info;
68
    private Document doc;
69
    
67
    
70
    Map<ElementHandle<TypeElement>, List<ElementHandle<ExecutableElement>>> type2Declaration;
68
    Map<ElementHandle<TypeElement>, List<ElementHandle<ExecutableElement>>> type2Declaration;
71
    Map<ElementHandle<ExecutableElement>, MethodTree> declaration2Tree;
69
    Map<ElementHandle<ExecutableElement>, MethodTree> declaration2Tree;
Lines 73-80 Link Here
73
    
71
    
74
    private Map<TypeElement, ElementHandle<TypeElement>> type2Handle;
72
    private Map<TypeElement, ElementHandle<TypeElement>> type2Handle;
75
    
73
    
76
    IsOverriddenVisitor(Document doc, CompilationInfo info) {
74
    IsOverriddenVisitor(CompilationInfo info, AtomicBoolean cancel) {
77
        this.doc = doc;
75
        super(cancel);
78
        this.info = info;
76
        this.info = info;
79
        
77
        
80
        type2Declaration = new HashMap<ElementHandle<TypeElement>, List<ElementHandle<ExecutableElement>>>();
78
        type2Declaration = new HashMap<ElementHandle<TypeElement>, List<ElementHandle<ExecutableElement>>>();
(-)a/java.editor/src/org/netbeans/modules/java/editor/resources/Bundle.properties (-1 / +1 lines)
Lines 23-29 Link Here
23
# Contributor(s):
23
# Contributor(s):
24
#
24
#
25
# The Original Software is NetBeans. The Initial Developer of the Original
25
# The Original Software is NetBeans. The Initial Developer of the Original
26
# Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
26
# Software is Sun Microsystems, Inc. Portions Copyright 1997-2009 Sun
27
# Microsystems, Inc. All Rights Reserved.
27
# Microsystems, Inc. All Rights Reserved.
28
#
28
#
29
# If you wish your version of this file to be governed by only the CDDL
29
# If you wish your version of this file to be governed by only the CDDL
(-)a/java.editor/src/org/netbeans/modules/java/editor/resources/DefaultKeyBindings.xml (+1 lines)
Lines 51-56 Link Here
51
    <bind actionName="fast-import" key="OS-I"/>
51
    <bind actionName="fast-import" key="OS-I"/>
52
    <bind actionName="fix-imports" key="DS-I"/>
52
    <bind actionName="fix-imports" key="DS-I"/>
53
    <bind actionName="goto-super-implementation" key="DS-P"/>
53
    <bind actionName="goto-super-implementation" key="DS-P"/>
54
    <bind actionName="goto-implementation" key="DA-B"/>
54
    <bind actionName="goto-help" key="O-F1"/>
55
    <bind actionName="goto-help" key="O-F1"/>
55
<!--    <bind actionName="make-is" key="O-U$I"/> -->
56
<!--    <bind actionName="make-is" key="O-U$I"/> -->
56
<!--    <bind actionName="make-getter" key="O-U$G"/> -->
57
<!--    <bind actionName="make-getter" key="O-U$G"/> -->
(-)a/java.editor/src/org/netbeans/modules/java/editor/resources/has-implementations-annotation.xml (-2 / +2 lines)
Lines 44-50 Link Here
44
                 "-//NetBeans//DTD annotation type 1.0//EN"
44
                 "-//NetBeans//DTD annotation type 1.0//EN"
45
                 "http://www.netbeans.org/dtds/annotation-type-1_0.dtd">
45
                 "http://www.netbeans.org/dtds/annotation-type-1_0.dtd">
46
       <type name="org-netbeans-modules-editor-java-has_implementations"
46
       <type name="org-netbeans-modules-editor-java-has_implementations"
47
             description_key="LAB_IsOverridenAnnotation"
47
             description_key="LAB_HasImplementationsAnnotation"
48
             localizing_bundle="org.netbeans.modules.java.Bundle"
48
             localizing_bundle="org.netbeans.modules.java.editor.overridden.Bundle"
49
             visible="true"
49
             visible="true"
50
             glyph="nbresloc:/org/netbeans/modules/java/editor/resources/has-implementations.png"/>
50
             glyph="nbresloc:/org/netbeans/modules/java/editor/resources/has-implementations.png"/>
(-)a/java.editor/src/org/netbeans/modules/java/editor/resources/implements-annotation.xml (-2 / +2 lines)
Lines 44-51 Link Here
44
                 "-//NetBeans//DTD annotation type 1.1//EN"
44
                 "-//NetBeans//DTD annotation type 1.1//EN"
45
                 "http://www.netbeans.org/dtds/annotation-type-1_1.dtd">
45
                 "http://www.netbeans.org/dtds/annotation-type-1_1.dtd">
46
       <type name="org-netbeans-modules-editor-java-implements"
46
       <type name="org-netbeans-modules-editor-java-implements"
47
             description_key="LAB_IsOverridenAnnotation"
47
             description_key="LAB_ImplementsAnnotation"
48
             localizing_bundle="org.netbeans.modules.java.Bundle"
48
             localizing_bundle="org.netbeans.modules.java.editor.overridden.Bundle"
49
             visible="true"
49
             visible="true"
50
             glyph="nbresloc:/org/netbeans/modules/java/editor/resources/implements.png"
50
             glyph="nbresloc:/org/netbeans/modules/java/editor/resources/implements.png"
51
             priority="5"/>
51
             priority="5"/>
(-)a/java.editor/src/org/netbeans/modules/java/editor/resources/implements-has-implementations-combined.xml (+55 lines)
Line 0 Link Here
1
<?xml version="1.0" encoding="UTF-8"?>
2
<!--
3
DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
4
5
Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
6
7
8
The contents of this file are subject to the terms of either the GNU
9
General Public License Version 2 only ("GPL") or the Common
10
Development and Distribution License("CDDL") (collectively, the
11
"License"). You may not use this file except in compliance with the
12
License. You can obtain a copy of the License at
13
http://www.netbeans.org/cddl-gplv2.html
14
or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
15
specific language governing permissions and limitations under the
16
License.  When distributing the software, include this License Header
17
Notice in each file and include the License file at
18
nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
19
particular file as subject to the "Classpath" exception as provided
20
by Sun in the GPL Version 2 section of the License file that
21
accompanied this code. If applicable, add the following below the
22
License Header, with the fields enclosed by brackets [] replaced by
23
your own identifying information:
24
"Portions Copyrighted [year] [name of copyright owner]"
25
26
Contributor(s):
27
28
The Original Software is NetBeans. The Initial Developer of the Original
29
Software is Sun Microsystems, Inc. Portions Copyright 1997-2009 Sun
30
Microsystems, Inc. All Rights Reserved.
31
32
If you wish your version of this file to be governed by only the CDDL
33
or only the GPL Version 2, indicate your decision by adding
34
"[Contributor] elects to include this software in this distribution
35
under the [CDDL or GPL Version 2] license." If you do not indicate a
36
single choice of license, a recipient has the option to distribute
37
your version of this file under either the CDDL, the GPL Version 2 or
38
to extend the choice of license to its licensees as provided above.
39
However, if you add GPL Version 2 code and therefore, elected the GPL
40
Version 2 license, then the option applies only if the new code is
41
made subject to such option by the copyright holder.
42
-->
43
<!DOCTYPE type PUBLIC
44
          "-//NetBeans//DTD annotation type 1.0//EN"
45
          "http://www.netbeans.org/dtds/annotation-type-1_0.dtd">
46
<type name="org-netbeans-modules-editor-java-implements-has-implementations-combined"
47
      description_key="LAB_IsOverridenAnnotation-implements-has-implementations-combined"
48
      localizing_bundle="org.netbeans.modules.java.editor.overridden.Bundle"
49
      visible="true"
50
      glyph="nbresloc:/org/netbeans/modules/java/editor/resources/override-is-overridden-combined.png">
51
    <combination tiptext_key="TP_COMBINED-implements-has-implementations-combined">
52
        <combine annotationtype="org-netbeans-modules-editor-java-has_implementations"/>
53
        <combine annotationtype="org-netbeans-modules-editor-java-implements"/>
54
    </combination>
55
</type>
(-)a/java.editor/src/org/netbeans/modules/java/editor/resources/implements-is-overridden-combined.xml (+55 lines)
Line 0 Link Here
1
<?xml version="1.0" encoding="UTF-8"?>
2
<!--
3
DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
4
5
Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
6
7
8
The contents of this file are subject to the terms of either the GNU
9
General Public License Version 2 only ("GPL") or the Common
10
Development and Distribution License("CDDL") (collectively, the
11
"License"). You may not use this file except in compliance with the
12
License. You can obtain a copy of the License at
13
http://www.netbeans.org/cddl-gplv2.html
14
or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
15
specific language governing permissions and limitations under the
16
License.  When distributing the software, include this License Header
17
Notice in each file and include the License file at
18
nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
19
particular file as subject to the "Classpath" exception as provided
20
by Sun in the GPL Version 2 section of the License file that
21
accompanied this code. If applicable, add the following below the
22
License Header, with the fields enclosed by brackets [] replaced by
23
your own identifying information:
24
"Portions Copyrighted [year] [name of copyright owner]"
25
26
Contributor(s):
27
28
The Original Software is NetBeans. The Initial Developer of the Original
29
Software is Sun Microsystems, Inc. Portions Copyright 1997-2009 Sun
30
Microsystems, Inc. All Rights Reserved.
31
32
If you wish your version of this file to be governed by only the CDDL
33
or only the GPL Version 2, indicate your decision by adding
34
"[Contributor] elects to include this software in this distribution
35
under the [CDDL or GPL Version 2] license." If you do not indicate a
36
single choice of license, a recipient has the option to distribute
37
your version of this file under either the CDDL, the GPL Version 2 or
38
to extend the choice of license to its licensees as provided above.
39
However, if you add GPL Version 2 code and therefore, elected the GPL
40
Version 2 license, then the option applies only if the new code is
41
made subject to such option by the copyright holder.
42
-->
43
<!DOCTYPE type PUBLIC
44
          "-//NetBeans//DTD annotation type 1.0//EN"
45
          "http://www.netbeans.org/dtds/annotation-type-1_0.dtd">
46
<type name="org-netbeans-modules-editor-java-implements-is-overridden-combined"
47
      description_key="LAB_IsOverridenAnnotation-implements-is-overridden-combined"
48
      localizing_bundle="org.netbeans.modules.java.editor.overridden.Bundle"
49
      visible="true"
50
      glyph="nbresloc:/org/netbeans/modules/java/editor/resources/override-is-overridden-combined.png">
51
    <combination tiptext_key="TP_COMBINED-implements-is-overridden-combined">
52
        <combine annotationtype="org-netbeans-modules-editor-java-is_overridden"/>
53
        <combine annotationtype="org-netbeans-modules-editor-java-implements"/>
54
    </combination>
55
</type>
(-)a/java.editor/src/org/netbeans/modules/java/editor/resources/is-overridden-annotation.xml (-1 / +1 lines)
Lines 45-51 Link Here
45
                 "http://www.netbeans.org/dtds/annotation-type-1_1.dtd">
45
                 "http://www.netbeans.org/dtds/annotation-type-1_1.dtd">
46
       <type name="org-netbeans-modules-editor-java-is_overridden"
46
       <type name="org-netbeans-modules-editor-java-is_overridden"
47
             description_key="LAB_IsOverridenAnnotation"
47
             description_key="LAB_IsOverridenAnnotation"
48
             localizing_bundle="org.netbeans.modules.java.Bundle"
48
             localizing_bundle="org.netbeans.modules.java.editor.overridden.Bundle"
49
             visible="true"
49
             visible="true"
50
             glyph="nbresloc:/org/netbeans/modules/java/editor/resources/is-overridden.png"
50
             glyph="nbresloc:/org/netbeans/modules/java/editor/resources/is-overridden.png"
51
             priority="5"/>
51
             priority="5"/>
(-)a/java.editor/src/org/netbeans/modules/java/editor/resources/layer.xml (+7 lines)
Lines 118-123 Link Here
118
                <file name="org-netbeans-modules-java-editor-semantic-HighlightsLayerFactoryImpl.instance" />
118
                <file name="org-netbeans-modules-java-editor-semantic-HighlightsLayerFactoryImpl.instance" />
119
                <file name="org-netbeans-modules-java-editor-semantic-SemanticHighlighterFactory.instance" />
119
                <file name="org-netbeans-modules-java-editor-semantic-SemanticHighlighterFactory.instance" />
120
                <file name="org-netbeans-modules-java-editor-semantic-MarkOccurrencesHighlighterFactory.instance" />
120
                <file name="org-netbeans-modules-java-editor-semantic-MarkOccurrencesHighlighterFactory.instance" />
121
                <file name="org-netbeans-modules-java-editor-overridden-ComputeAnnotations$FactoryImpl.instance" />
121
                
122
                
122
                <folder name="Preferences">
123
                <folder name="Preferences">
123
                    <folder name="Defaults">
124
                    <folder name="Defaults">
Lines 300-305 Link Here
300
                        <file name="goto-super-implementation">
301
                        <file name="goto-super-implementation">
301
                            <attr name="position" intvalue="300"/>
302
                            <attr name="position" intvalue="300"/>
302
                        </file>  
303
                        </file>  
304
                        <file name="goto-implementation">
305
                            <attr name="position" intvalue="330"/>
306
                        </file>
303
                    </folder>
307
                    </folder>
304
                    
308
                    
305
                    <file name="goto-help">
309
                    <file name="goto-help">
Lines 431-436 Link Here
431
            <file name="org-netbeans-modules-editor-java-has_implementations.xml" url="has-implementations-annotation.xml"/>
435
            <file name="org-netbeans-modules-editor-java-has_implementations.xml" url="has-implementations-annotation.xml"/>
432
            <file name="org-netbeans-modules-editor-java-overrides.xml" url="overrides-annotation.xml"/>
436
            <file name="org-netbeans-modules-editor-java-overrides.xml" url="overrides-annotation.xml"/>
433
            <file name="org-netbeans-modules-editor-java-implements.xml" url="implements-annotation.xml"/>
437
            <file name="org-netbeans-modules-editor-java-implements.xml" url="implements-annotation.xml"/>
438
            <file name="implements-has-implementations-combined.xml" url="implements-has-implementations-combined.xml" />
439
            <file name="implements-is-overridden-combined.xml" url="implements-is-overridden-combined.xml" />
440
            <file name="override-is-overridden-combined.xml" url="override-is-overridden-combined.xml" />
434
        </folder>
441
        </folder>
435
    </folder>
442
    </folder>
436
443
(-)a/java.editor/src/org/netbeans/modules/java/editor/resources/override-is-overridden-combined.xml (+55 lines)
Line 0 Link Here
1
<?xml version="1.0" encoding="UTF-8"?>
2
<!--
3
DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
4
5
Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
6
7
8
The contents of this file are subject to the terms of either the GNU
9
General Public License Version 2 only ("GPL") or the Common
10
Development and Distribution License("CDDL") (collectively, the
11
"License"). You may not use this file except in compliance with the
12
License. You can obtain a copy of the License at
13
http://www.netbeans.org/cddl-gplv2.html
14
or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
15
specific language governing permissions and limitations under the
16
License.  When distributing the software, include this License Header
17
Notice in each file and include the License file at
18
nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
19
particular file as subject to the "Classpath" exception as provided
20
by Sun in the GPL Version 2 section of the License file that
21
accompanied this code. If applicable, add the following below the
22
License Header, with the fields enclosed by brackets [] replaced by
23
your own identifying information:
24
"Portions Copyrighted [year] [name of copyright owner]"
25
26
Contributor(s):
27
28
The Original Software is NetBeans. The Initial Developer of the Original
29
Software is Sun Microsystems, Inc. Portions Copyright 1997-2009 Sun
30
Microsystems, Inc. All Rights Reserved.
31
32
If you wish your version of this file to be governed by only the CDDL
33
or only the GPL Version 2, indicate your decision by adding
34
"[Contributor] elects to include this software in this distribution
35
under the [CDDL or GPL Version 2] license." If you do not indicate a
36
single choice of license, a recipient has the option to distribute
37
your version of this file under either the CDDL, the GPL Version 2 or
38
to extend the choice of license to its licensees as provided above.
39
However, if you add GPL Version 2 code and therefore, elected the GPL
40
Version 2 license, then the option applies only if the new code is
41
made subject to such option by the copyright holder.
42
-->
43
<!DOCTYPE type PUBLIC
44
          "-//NetBeans//DTD annotation type 1.0//EN"
45
          "http://www.netbeans.org/dtds/annotation-type-1_0.dtd">
46
<type name="org-netbeans-modules-editor-java-override-is-overridden-combined"
47
      description_key="LAB_IsOverridenAnnotation-override-is-overridden-combined"
48
      localizing_bundle="org.netbeans.modules.java.editor.overridden.Bundle"
49
      visible="true"
50
      glyph="nbresloc:/org/netbeans/modules/java/editor/resources/override-is-overridden-combined.png">
51
    <combination tiptext_key="TP_COMBINED-override-is-overridden-combined">
52
        <combine annotationtype="org-netbeans-modules-editor-java-is_overridden"/>
53
        <combine annotationtype="org-netbeans-modules-editor-java-overrides"/>
54
    </combination>
55
</type>
(-)a/java.editor/src/org/netbeans/modules/java/editor/resources/overrides-annotation.xml (-2 / +2 lines)
Lines 44-50 Link Here
44
                 "-//NetBeans//DTD annotation type 1.0//EN"
44
                 "-//NetBeans//DTD annotation type 1.0//EN"
45
                 "http://www.netbeans.org/dtds/annotation-type-1_0.dtd">
45
                 "http://www.netbeans.org/dtds/annotation-type-1_0.dtd">
46
       <type name="org-netbeans-modules-editor-java-overrides"
46
       <type name="org-netbeans-modules-editor-java-overrides"
47
             description_key="LAB_IsOverridenAnnotation"
47
             description_key="LAB_OverridesAnnotation"
48
             localizing_bundle="org.netbeans.modules.java.Bundle"
48
             localizing_bundle="org.netbeans.modules.java.editor.overridden.Bundle"
49
             visible="true"
49
             visible="true"
50
             glyph="nbresloc:/org/netbeans/modules/java/editor/resources/overrides.png"/>
50
             glyph="nbresloc:/org/netbeans/modules/java/editor/resources/overrides.png"/>
(-)a/java.editor/test/unit/src/org/netbeans/modules/java/editor/overridden/ComputeOverridersTest.java (+312 lines)
Line 0 Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
5
 *
6
 * The contents of this file are subject to the terms of either the GNU
7
 * General Public License Version 2 only ("GPL") or the Common
8
 * Development and Distribution License("CDDL") (collectively, the
9
 * "License"). You may not use this file except in compliance with the
10
 * License. You can obtain a copy of the License at
11
 * http://www.netbeans.org/cddl-gplv2.html
12
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
13
 * specific language governing permissions and limitations under the
14
 * License.  When distributing the software, include this License Header
15
 * Notice in each file and include the License file at
16
 * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
17
 * particular file as subject to the "Classpath" exception as provided
18
 * by Sun in the GPL Version 2 section of the License file that
19
 * accompanied this code. If applicable, add the following below the
20
 * License Header, with the fields enclosed by brackets [] replaced by
21
 * your own identifying information:
22
 * "Portions Copyrighted [year] [name of copyright owner]"
23
 *
24
 * If you wish your version of this file to be governed by only the CDDL
25
 * or only the GPL Version 2, indicate your decision by adding
26
 * "[Contributor] elects to include this software in this distribution
27
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
28
 * single choice of license, a recipient has the option to distribute
29
 * your version of this file under either the CDDL, the GPL Version 2 or
30
 * to extend the choice of license to its licensees as provided above.
31
 * However, if you add GPL Version 2 code and therefore, elected the GPL
32
 * Version 2 license, then the option applies only if the new code is
33
 * made subject to such option by the copyright holder.
34
 *
35
 * Contributor(s):
36
 *
37
 * Portions Copyrighted 2009 Sun Microsystems, Inc.
38
 */
39
40
package org.netbeans.modules.java.editor.overridden;
41
42
import java.io.File;
43
import java.net.URL;
44
import java.util.Arrays;
45
import java.util.Collections;
46
import java.util.HashMap;
47
import java.util.LinkedHashMap;
48
import java.util.LinkedList;
49
import java.util.List;
50
import java.util.Map;
51
import java.util.Map.Entry;
52
import java.util.concurrent.atomic.AtomicBoolean;
53
import javax.lang.model.element.Element;
54
import javax.swing.event.ChangeListener;
55
import org.netbeans.api.java.classpath.ClassPath;
56
import org.netbeans.api.java.queries.SourceForBinaryQuery;
57
import org.netbeans.api.java.source.CompilationInfo;
58
import org.netbeans.api.java.source.ElementHandle;
59
import org.netbeans.api.java.source.JavaSource;
60
import org.netbeans.api.java.source.JavaSource.Phase;
61
import org.netbeans.api.java.source.SourceUtilsTestUtil;
62
import org.netbeans.api.java.source.SourceUtilsTestUtil.TestSourceLevelQueryImplementation;
63
import org.netbeans.api.java.source.TestUtilities;
64
import org.netbeans.core.startup.Main;
65
import org.netbeans.junit.NbTestCase;
66
import org.netbeans.modules.java.JavaDataLoader;
67
import org.netbeans.modules.java.source.usages.IndexUtil;
68
import org.netbeans.modules.parsing.impl.indexing.RepositoryUpdater;
69
import org.netbeans.spi.java.classpath.ClassPathProvider;
70
import org.netbeans.spi.java.classpath.support.ClassPathSupport;
71
import org.netbeans.spi.java.queries.SourceForBinaryQueryImplementation;
72
import org.openide.filesystems.FileObject;
73
import org.openide.filesystems.FileUtil;
74
import org.openide.filesystems.URLMapper;
75
76
/**
77
 *
78
 * @author Jan Lahoda
79
 */
80
public class ComputeOverridersTest extends NbTestCase {
81
82
    public ComputeOverridersTest(String name) {
83
        super(name);
84
    }
85
86
    public void testSimple1() throws Exception {
87
        prepareSourceRoot("1");
88
        prepareSource("1",
89
                      "test/Test.java",
90
                      "package test;" +
91
                      "public abstract class Test {" +
92
                      "     protected abstract void test();" +
93
                      "}");
94
        prepareSourceRoot("2", "1");
95
        prepareSource("2",
96
                      "dep/Dep.java",
97
                      "package dep;" +
98
                      "public class Dep extends test.Test {" +
99
                      "     protected void test() {}" +
100
                      "}");
101
        prepareSourceRoot("3", "1");
102
        prepareSource("3",
103
                      "dep3/Dep3.java",
104
                      "package dep3;" +
105
                      "public class Dep3 extends test.Test {" +
106
                      "     protected void test() {}" +
107
                      "}");
108
        prepareSourceRoot("4", "1", "2");
109
        prepareSource("4",
110
                      "dep4/Dep4.java",
111
                      "package dep4;" +
112
                      "public class Dep4 extends dep.Dep {" +
113
                      "     protected void test() {}" +
114
                      "}");
115
116
        FileObject file = sourceDirectories.getFileObject("1/test/Test.java");
117
118
        CompilationInfo info = SourceUtilsTestUtil.getCompilationInfo(JavaSource.forFileObject(file), Phase.RESOLVED);
119
        URL r1 = sourceDirectories.getFileObject("1").getURL();
120
        URL r2 = sourceDirectories.getFileObject("2").getURL();
121
        URL r3 = sourceDirectories.getFileObject("3").getURL();
122
        URL r4 = sourceDirectories.getFileObject("4").getURL();
123
124
        ComputeOverriders.reverseSourceRootsInOrderOverride = Arrays.asList(r1, r2, r3, r4);
125
126
        ComputeOverriders.dependenciesOverride = new HashMap<URL, List<URL>>();
127
        ComputeOverriders.dependenciesOverride.put(r1, Collections.<URL>emptyList());
128
        ComputeOverriders.dependenciesOverride.put(r2, Collections.singletonList(r1));
129
        ComputeOverriders.dependenciesOverride.put(r3, Collections.singletonList(r1));
130
        ComputeOverriders.dependenciesOverride.put(r4, Arrays.asList(r1, r2));
131
        
132
        Map<ElementHandle<? extends Element>, List<ElementDescription>> output = new ComputeOverriders(new AtomicBoolean()).process(info, null, null, false);
133
        Map<String, List<String>> outputStrings = new LinkedHashMap<String, List<String>>();
134
135
        for (Entry<ElementHandle<? extends Element>, List<ElementDescription>> e : output.entrySet()) {
136
            List<String> descs = new LinkedList<String>();
137
138
            for (ElementDescription ed : e.getValue()) {
139
                descs.add(ed.getHandle().toString());
140
            }
141
142
            outputStrings.put(e.getKey().toString(), descs);
143
        }
144
145
        Map<String, List<String>> golden = new LinkedHashMap<String, List<String>>();
146
147
        golden.put("ElementHandle[kind=CLASS; sigs=test.Test ]", Arrays.asList(
148
            "ElementHandle[kind=CLASS; sigs=dep.Dep ]",
149
            "ElementHandle[kind=CLASS; sigs=dep3.Dep3 ]",
150
            "ElementHandle[kind=CLASS; sigs=dep4.Dep4 ]"
151
        ));
152
        golden.put("ElementHandle[kind=METHOD; sigs=test.Test test ()V ]", Arrays.asList(
153
            "ElementHandle[kind=METHOD; sigs=dep.Dep test ()V ]",
154
            "ElementHandle[kind=METHOD; sigs=dep3.Dep3 test ()V ]",
155
            "ElementHandle[kind=METHOD; sigs=dep4.Dep4 test ()V ]"
156
        ));
157
158
        assertEquals(golden, outputStrings);
159
    }
160
161
162
    private Map<FileObject, ClassPath> root2ClassPath = new HashMap<FileObject, ClassPath>();
163
    private Map<FileObject, FileObject> root2BuildRoot = new HashMap<FileObject, FileObject>();
164
    private Map<FileObject, FileObject> buildRoot2Source = new HashMap<FileObject, FileObject>();
165
166
    private FileObject sourceDirectories;
167
    private FileObject buildDirectories;
168
169
    private void prepareSourceRoot(String name, String... dependsOn) throws Exception {
170
        FileObject src = FileUtil.createFolder(sourceDirectories, name);
171
        FileObject build = FileUtil.createFolder(buildDirectories, name);
172
173
        List<FileObject> dependencies = new LinkedList<FileObject>();
174
175
        for(String dep : dependsOn) {
176
            FileObject depFO = buildDirectories.getFileObject(dep);
177
178
            assertNotNull(depFO);
179
            dependencies.add(depFO);
180
        }
181
182
        root2ClassPath.put(src, ClassPathSupport.createClassPath(dependencies.toArray(new FileObject[0])));
183
        root2BuildRoot.put(src, build);
184
        buildRoot2Source.put(build, src);
185
    }
186
187
    private void prepareSource(String sourceRoot, String fileName, String code) throws Exception {
188
        FileObject root = sourceDirectories.getFileObject(sourceRoot);
189
190
        assertNotNull(root);
191
192
        FileObject source = FileUtil.createData(root, fileName);
193
194
        TestUtilities.copyStringToFile(source, code);
195
196
        SourceUtilsTestUtil.compileRecursively(root);
197
    }
198
    
199
    public void setUp() throws Exception {
200
        SourceUtilsTestUtil.setLookup(new Object[0], ComputeOverridersTest.class.getClassLoader());
201
        Main.initializeURLFactory();
202
        
203
        clearWorkDir();
204
        File wd = getWorkDir();
205
        assert wd.isDirectory() && wd.list().length == 0;
206
        FileObject dir = FileUtil.toFileObject(wd);
207
208
        assertNotNull(dir);
209
210
        sourceDirectories = FileUtil.createFolder(dir, "src");
211
        buildDirectories = FileUtil.createFolder(dir, "build");
212
213
        FileObject cache = FileUtil.createFolder(dir, "cache");
214
215
        List<Object> lookupContent = new LinkedList<Object>();
216
217
        lookupContent.add(new TestProxyClassPathProvider());
218
        lookupContent.add(new TestSourceForBinaryQuery());
219
        lookupContent.add(new TestSourceLevelQueryImplementation());
220
        lookupContent.add(JavaDataLoader.findObject(JavaDataLoader.class, true));
221
222
        SourceUtilsTestUtil.setLookup(lookupContent.toArray(), SourceUtilsTestUtil.class.getClassLoader());
223
224
        IndexUtil.setCacheFolder(FileUtil.toFile(cache));
225
226
        RepositoryUpdater.getDefault().start(true);
227
    }
228
229
    private FileObject findRoot(FileObject file) {
230
        FileObject root = null;
231
        for (Entry<FileObject, ClassPath> e : root2ClassPath.entrySet()) {
232
            if (e.getKey() == file || FileUtil.isParentOf(e.getKey(), file)) {
233
                root = e.getKey();
234
                break;
235
            }
236
        }
237
        return root;
238
    }
239
240
    private class TestProxyClassPathProvider implements ClassPathProvider {
241
242
        public ClassPath findClassPath(FileObject file, String type) {
243
            try {
244
                FileObject root = findRoot(file);
245
246
                if (root == null) {
247
                    return null;
248
                }
249
                
250
                if (ClassPath.BOOT == type) {
251
                    return ClassPathSupport.createClassPath(SourceUtilsTestUtil.getBootClassPath().toArray(new URL[0]));
252
                }
253
254
                if (ClassPath.SOURCE == type) {
255
                    return ClassPathSupport.createClassPath(new FileObject[] {
256
                        root
257
                    });
258
                }
259
260
                if (ClassPath.COMPILE == type) {
261
                    return root2ClassPath.get(root);
262
                }
263
264
                if (ClassPath.EXECUTE == type) {
265
                    return ClassPathSupport.createProxyClassPath(
266
                            root2ClassPath.get(root),
267
                            ClassPathSupport.createClassPath(new FileObject[] {
268
                                root2BuildRoot.get(root)
269
                            })
270
                           );
271
                }
272
            } catch (Exception e) {
273
                e.printStackTrace();
274
            }
275
            return null;
276
        }
277
278
    }
279
280
    private class TestSourceForBinaryQuery implements SourceForBinaryQueryImplementation {
281
282
        public SourceForBinaryQuery.Result findSourceRoots(URL binaryRoot) {
283
            if (SourceUtilsTestUtil.getBootClassPath().contains(binaryRoot))
284
                return null;
285
286
            FileObject file = URLMapper.findFileObject(binaryRoot);
287
288
            if (file == null) {
289
                return null;
290
            }
291
            
292
            final FileObject source = buildRoot2Source.get(file);
293
294
            if (source == null) {
295
                return null;
296
            }
297
298
            return new SourceForBinaryQuery.Result() {
299
                public FileObject[] getRoots() {
300
                    return new FileObject[] {
301
                        source,
302
                    };
303
                }
304
305
                public void addChangeListener(ChangeListener l) {}
306
                public void removeChangeListener(ChangeListener l) {}
307
            };
308
        }
309
310
    }
311
    
312
}
(-)a/java.editor/test/unit/src/org/netbeans/modules/java/editor/overridden/IsOverriddenAnnotationCreatorTest.java (-14 / +14 lines)
Lines 187-206 Link Here
187
        
187
        
188
        StyledDocument doc = ec.openDocument();
188
        StyledDocument doc = ec.openDocument();
189
        
189
        
190
        List<IsOverriddenAnnotation> annotations = new IsOverriddenAnnotationHandler(testSource).process(info, doc);
190
//        List<IsOverriddenAnnotation> annotations = new ComputeOverriding(testSource).process(info, doc);
191
        List<String> result = new ArrayList<String>();
191
//        List<String> result = new ArrayList<String>();
192
        
192
//
193
        for (IsOverriddenAnnotation annotation : annotations) {
193
//        for (IsOverriddenAnnotation annotation : annotations) {
194
            result.add(annotation.debugDump());
194
//            result.add(annotation.debugDump());
195
        }
195
//        }
196
        
196
//
197
        Collections.sort(result);
197
//        Collections.sort(result);
198
        
198
//
199
        for (String r : result) {
199
//        for (String r : result) {
200
            ref(r);
200
//            ref(r);
201
        }
201
//        }
202
        
202
//
203
        compareReferenceFiles();
203
//        compareReferenceFiles();
204
    }
204
    }
205
    
205
    
206
    /**Copied from org.netbeans.api.project.
206
    /**Copied from org.netbeans.api.project.
(-)a/java.hints/src/org/netbeans/modules/java/hints/AddOverrideAnnotation.java (-2 / +2 lines)
Lines 71-78 Link Here
71
import org.netbeans.api.java.source.WorkingCopy;
71
import org.netbeans.api.java.source.WorkingCopy;
72
import org.netbeans.modules.java.editor.codegen.GeneratorUtils;
72
import org.netbeans.modules.java.editor.codegen.GeneratorUtils;
73
import org.netbeans.modules.java.editor.overridden.AnnotationType;
73
import org.netbeans.modules.java.editor.overridden.AnnotationType;
74
import org.netbeans.modules.java.editor.overridden.ComputeOverriding;
74
import org.netbeans.modules.java.editor.overridden.ElementDescription;
75
import org.netbeans.modules.java.editor.overridden.ElementDescription;
75
import org.netbeans.modules.java.editor.overridden.IsOverriddenAnnotationHandler;
76
import org.netbeans.modules.java.hints.spi.AbstractHint;
76
import org.netbeans.modules.java.hints.spi.AbstractHint;
77
import org.netbeans.spi.editor.hints.ChangeInfo;
77
import org.netbeans.spi.editor.hints.ChangeInfo;
78
import org.netbeans.spi.editor.hints.ErrorDescription;
78
import org.netbeans.spi.editor.hints.ErrorDescription;
Lines 109-115 Link Here
109
            ExecutableElement ee = (ExecutableElement) e;
109
            ExecutableElement ee = (ExecutableElement) e;
110
            List<ElementDescription> result = new ArrayList<ElementDescription>();
110
            List<ElementDescription> result = new ArrayList<ElementDescription>();
111
111
112
            AnnotationType type = IsOverriddenAnnotationHandler.detectOverrides(compilationInfo, (TypeElement) ee.getEnclosingElement(), ee, result);
112
            AnnotationType type = ComputeOverriding.detectOverrides(compilationInfo, (TypeElement) ee.getEnclosingElement(), ee, result);
113
113
114
            boolean hasOverriddenAnnotation = false;
114
            boolean hasOverriddenAnnotation = false;
115
115
(-)a/java.hints/src/org/netbeans/modules/java/hints/errors/UncaughtException.java (-2 / +2 lines)
Lines 83-90 Link Here
83
import org.netbeans.api.java.source.WorkingCopy;
83
import org.netbeans.api.java.source.WorkingCopy;
84
import org.netbeans.modules.editor.java.Utilities;
84
import org.netbeans.modules.editor.java.Utilities;
85
import org.netbeans.modules.java.editor.overridden.AnnotationType;
85
import org.netbeans.modules.java.editor.overridden.AnnotationType;
86
import org.netbeans.modules.java.editor.overridden.ComputeOverriding;
86
import org.netbeans.modules.java.editor.overridden.ElementDescription;
87
import org.netbeans.modules.java.editor.overridden.ElementDescription;
87
import org.netbeans.modules.java.editor.overridden.IsOverriddenAnnotationHandler;
88
import org.netbeans.modules.java.hints.spi.ErrorRule;
88
import org.netbeans.modules.java.hints.spi.ErrorRule;
89
import org.netbeans.spi.editor.hints.ChangeInfo;
89
import org.netbeans.spi.editor.hints.ChangeInfo;
90
import org.netbeans.spi.editor.hints.Fix;
90
import org.netbeans.spi.editor.hints.Fix;
Lines 222-228 Link Here
222
                if (!org.netbeans.modules.java.hints.errors.Utilities.isMethodHeaderInsideGuardedBlock(info, (MethodTree) pathRec.getLeaf())) {
222
                if (!org.netbeans.modules.java.hints.errors.Utilities.isMethodHeaderInsideGuardedBlock(info, (MethodTree) pathRec.getLeaf())) {
223
                    List<ElementDescription> eds = new LinkedList<ElementDescription>();
223
                    List<ElementDescription> eds = new LinkedList<ElementDescription>();
224
                    TypeElement enclosingType = (TypeElement) method.getEnclosingElement();
224
                    TypeElement enclosingType = (TypeElement) method.getEnclosingElement();
225
                    AnnotationType at = IsOverriddenAnnotationHandler.detectOverrides(info, enclosingType, method,eds);
225
                    AnnotationType at = ComputeOverriding.detectOverrides(info, enclosingType, method,eds);
226
                    List<TypeMirror> declaredThrows = null;
226
                    List<TypeMirror> declaredThrows = null;
227
                    
227
                    
228
                    if (at != null) {
228
                    if (at != null) {
(-)a/java.j2seplatform/src/org/netbeans/modules/java/j2seplatform/libraries/J2SELibrarySourceForBinaryQuery.java (-1 / +1 lines)
Lines 148-154 Link Here
148
     * @param URL url
148
     * @param URL url
149
     * @return true if  the URL is normal
149
     * @return true if  the URL is normal
150
     */
150
     */
151
    private static boolean isNormalizedURL (URL url) throws MalformedURLException {
151
    static boolean isNormalizedURL (URL url) throws MalformedURLException {
152
        if ("jar".equals(url.getProtocol())) { //NOI18N
152
        if ("jar".equals(url.getProtocol())) { //NOI18N
153
            String path = url.getPath();
153
            String path = url.getPath();
154
            int index = path.indexOf("!/"); //NOI18N
154
            int index = path.indexOf("!/"); //NOI18N

Return to bug 177396