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 212656
Collapse All | Expand All

(-)apisupport.ant/nbproject/project.xml (+36 lines)
Lines 155-160 Link Here
155
                    </run-dependency>
155
                    </run-dependency>
156
                </dependency>
156
                </dependency>
157
                <dependency>
157
                <dependency>
158
                    <code-name-base>org.netbeans.modules.java.hints.legacy.spi</code-name-base>
159
                    <build-prerequisite/>
160
                    <compile-dependency/>
161
                    <run-dependency>
162
                        <release-version>1</release-version>
163
                        <specification-version>1.7</specification-version>
164
                    </run-dependency>
165
                </dependency>
166
                <dependency>
167
                    <code-name-base>org.netbeans.modules.java.lexer</code-name-base>
168
                    <build-prerequisite/>
169
                    <compile-dependency/>
170
                    <run-dependency>
171
                        <release-version>1</release-version>
172
                        <specification-version>1.24</specification-version>
173
                    </run-dependency>
174
                </dependency>
175
                <dependency>
158
                    <code-name-base>org.netbeans.modules.java.platform</code-name-base>
176
                    <code-name-base>org.netbeans.modules.java.platform</code-name-base>
159
                    <build-prerequisite/>
177
                    <build-prerequisite/>
160
                    <compile-dependency/>
178
                    <compile-dependency/>
Lines 187-192 Link Here
187
                    </run-dependency>
205
                    </run-dependency>
188
                </dependency>
206
                </dependency>
189
                <dependency>
207
                <dependency>
208
                    <code-name-base>org.netbeans.modules.lexer</code-name-base>
209
                    <build-prerequisite/>
210
                    <compile-dependency/>
211
                    <run-dependency>
212
                        <release-version>2</release-version>
213
                        <specification-version>1.51</specification-version>
214
                    </run-dependency>
215
                </dependency>
216
                <dependency>
190
                    <code-name-base>org.netbeans.modules.project.ant</code-name-base>
217
                    <code-name-base>org.netbeans.modules.project.ant</code-name-base>
191
                    <build-prerequisite/>
218
                    <build-prerequisite/>
192
                    <compile-dependency/>
219
                    <compile-dependency/>
Lines 240-245 Link Here
240
                    </run-dependency>
267
                    </run-dependency>
241
                </dependency>
268
                </dependency>
242
                <dependency>
269
                <dependency>
270
                    <code-name-base>org.netbeans.spi.editor.hints</code-name-base>
271
                    <build-prerequisite/>
272
                    <compile-dependency/>
273
                    <run-dependency>
274
                        <release-version>0</release-version>
275
                        <specification-version>1.30</specification-version>
276
                    </run-dependency>
277
                </dependency>
278
                <dependency>
243
                    <code-name-base>org.netbeans.swing.outline</code-name-base>
279
                    <code-name-base>org.netbeans.swing.outline</code-name-base>
244
                    <build-prerequisite/>
280
                    <build-prerequisite/>
245
                    <compile-dependency/>
281
                    <compile-dependency/>
(-)apisupport.ant/src/org/netbeans/modules/apisupport/project/java/hints/errors/SearchModuleDependency.java (+415 lines)
Line 0 Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2010 Oracle and/or its affiliates. All rights reserved.
5
 *
6
 * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
7
 * Other names may be trademarks of their respective owners.
8
 *
9
 * The contents of this file are subject to the terms of either the GNU
10
 * General Public License Version 2 only ("GPL") or the Common
11
 * Development and Distribution License("CDDL") (collectively, the
12
 * "License"). You may not use this file except in compliance with the
13
 * License. You can obtain a copy of the License at
14
 * http://www.netbeans.org/cddl-gplv2.html
15
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
16
 * specific language governing permissions and limitations under the
17
 * License.  When distributing the software, include this License Header
18
 * Notice in each file and include the License file at
19
 * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
20
 * particular file as subject to the "Classpath" exception as provided
21
 * by Oracle in the GPL Version 2 section of the License file that
22
 * accompanied this code. If applicable, add the following below the
23
 * License Header, with the fields enclosed by brackets [] replaced by
24
 * your own identifying information:
25
 * "Portions Copyrighted [year] [name of copyright owner]"
26
 *
27
 * If you wish your version of this file to be governed by only the CDDL
28
 * or only the GPL Version 2, indicate your decision by adding
29
 * "[Contributor] elects to include this software in this distribution
30
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
31
 * single choice of license, a recipient has the option to distribute
32
 * your version of this file under either the CDDL, the GPL Version 2 or
33
 * to extend the choice of license to its licensees as provided above.
34
 * However, if you add GPL Version 2 code and therefore, elected the GPL
35
 * Version 2 license, then the option applies only if the new code is
36
 * made subject to such option by the copyright holder.
37
 *
38
 * Contributor(s): 
39
 *      theanuradha@netbeans.org
40
 *      markiewb@netbeans.org
41
 *
42
 * Portions Copyrighted 2008 Sun Microsystems, Inc.
43
 * Portions Copyrighted 2013 markiewb@netbeans.org
44
 */
45
package org.netbeans.modules.apisupport.project.java.hints.errors;
46
47
import com.sun.source.tree.ArrayTypeTree;
48
import com.sun.source.tree.ExpressionTree;
49
import com.sun.source.tree.IdentifierTree;
50
import com.sun.source.tree.MethodInvocationTree;
51
import com.sun.source.tree.NewArrayTree;
52
import com.sun.source.tree.NewClassTree;
53
import com.sun.source.tree.ParameterizedTypeTree;
54
import com.sun.source.tree.Tree;
55
import com.sun.source.tree.Tree.Kind;
56
import com.sun.source.tree.VariableTree;
57
import com.sun.source.util.TreePath;
58
import java.io.IOException;
59
import java.text.MessageFormat;
60
import java.util.ArrayList;
61
import java.util.Arrays;
62
import java.util.Collections;
63
import java.util.HashSet;
64
import java.util.List;
65
import java.util.Set;
66
import java.util.concurrent.atomic.AtomicBoolean;
67
import javax.lang.model.element.Name;
68
import org.netbeans.api.java.lexer.JavaTokenId;
69
import org.netbeans.api.java.source.CompilationInfo;
70
import org.netbeans.api.lexer.Token;
71
import org.netbeans.api.lexer.TokenHierarchy;
72
import org.netbeans.api.lexer.TokenSequence;
73
import org.netbeans.api.progress.ProgressUtils;
74
import org.netbeans.api.project.FileOwnerQuery;
75
import org.netbeans.api.project.Project;
76
import org.netbeans.api.project.ProjectManager;
77
import org.netbeans.modules.apisupport.project.ModuleDependency;
78
import org.netbeans.modules.apisupport.project.NbModuleProject;
79
import org.netbeans.modules.apisupport.project.ProjectXMLManager;
80
import org.netbeans.modules.apisupport.project.ui.customizer.AddModulePanel;
81
import org.netbeans.modules.apisupport.project.ui.customizer.SingleModuleProperties;
82
import org.netbeans.modules.java.hints.spi.ErrorRule.Data;
83
import org.netbeans.spi.editor.hints.ChangeInfo;
84
import org.netbeans.spi.editor.hints.EnhancedFix;
85
import org.netbeans.spi.editor.hints.Fix;
86
import org.openide.DialogDisplayer;
87
import org.openide.NotifyDescriptor;
88
import org.openide.filesystems.FileObject;
89
import org.openide.util.Exceptions;
90
import org.openide.util.NbBundle;
91
import org.openide.util.NbBundle.Messages;
92
93
/**
94
 * Fixable hint for an unresolved class which opens the NetBeans plattform
95
 * module dependency dialog. The dialog will be prefilled with the name of the
96
 * unresolved class.
97
 *
98
 * <ul> <li>Hint activation code taken from
99
 * {@link org.netbeans.modules.maven.hints.errors.SearchClassDependencyInRepo}</li>
100
 * <li>Dialog opening code taken from
101
 * {@link org.netbeans.modules.apisupport.project.ui.LibrariesNode.AddModuleDependencyAction}</li>
102
 * </ul>
103
 *
104
 * @author Anuradha G
105
 * @author markiewb
106
 */
107
108
@Messages({
109
    "LBL_Module_Dependency_Search_DisplayName=Add Module Dependency",
110
    "# {0} - name of unknown symbol",
111
    "FIX_Module_Dependency_Search=Search Module Dependency for {0}",
112
    "FIX_Module_Dependency_UpdatingDependencies=Update dependencies"
113
})
114
public class SearchModuleDependency implements org.netbeans.modules.java.hints.spi.ErrorRule<Void> {
115
116
    private AtomicBoolean cancel = new AtomicBoolean(false);
117
118
    public SearchModuleDependency() {
119
    }
120
121
    @Override
122
    public Set<String> getCodes() {
123
        return new HashSet<String>(Arrays.asList(
124
                "compiler.err.cant.resolve",//NOI18N
125
                "compiler.err.cant.resolve.location",//NOI18N
126
                "compiler.err.doesnt.exist",//NOI18N
127
                "compiler.err.not.stmt"));//NOI18N
128
129
    }
130
131
    private boolean isHintEnabled() {
132
        //TODO provide an option to disable this hint 
133
        return true;
134
    }
135
136
    @Override
137
    public List<Fix> run(final CompilationInfo info, String diagnosticKey,
138
            final int offset, TreePath treePath, Data<Void> data) {
139
        cancel.set(false);
140
        if (!isHintEnabled()) {
141
            return Collections.emptyList();
142
        }
143
        //copyed from ImportClass
144
        int errorPosition = offset + 1; //TODO: +1 required to work OK, rethink
145
146
        if (errorPosition == (-1)) {
147
148
            return Collections.<Fix>emptyList();
149
        }
150
        //copyed from ImportClass-end
151
        FileObject fileObject = info.getFileObject();
152
        Project project = FileOwnerQuery.getOwner(fileObject);
153
        if (project == null) {
154
            return Collections.emptyList();
155
        }
156
        NbModuleProject nbModuleProject = project.getLookup().lookup(NbModuleProject.class);
157
        if (nbModuleProject == null) {
158
            return Collections.emptyList();
159
        }
160
161
        //copyed from ImportClass
162
        TreePath path = info.getTreeUtilities().pathFor(errorPosition);
163
        if (path.getParentPath() == null) {
164
            return Collections.emptyList();
165
        }
166
167
        Tree leaf = path.getParentPath().getLeaf();
168
169
        switch (leaf.getKind()) {
170
            case METHOD_INVOCATION: {
171
                MethodInvocationTree mit = (MethodInvocationTree) leaf;
172
173
                if (!mit.getTypeArguments().contains(path.getLeaf())) {
174
                    return Collections.<Fix>emptyList();
175
                }
176
            }
177
            //genaric handling
178
179
            case PARAMETERIZED_TYPE: {
180
                leaf = path.getParentPath().getParentPath().getLeaf();
181
            }
182
            break;
183
            case ARRAY_TYPE: {
184
                leaf = path.getParentPath().getParentPath().getLeaf();
185
            }
186
            break;
187
        }
188
        switch (leaf.getKind()) {
189
            case VARIABLE: {
190
                Name typeName = null;
191
                VariableTree variableTree = (VariableTree) leaf;
192
                if (variableTree.getType() != null) {
193
                    switch (variableTree.getType().getKind()) {
194
                        case IDENTIFIER: {
195
                            typeName = ((IdentifierTree) variableTree.getType()).getName();
196
                        }
197
                        break;
198
                        case PARAMETERIZED_TYPE: {
199
                            ParameterizedTypeTree ptt = ((ParameterizedTypeTree) variableTree.getType());
200
                            if (ptt.getType() != null && ptt.getType().getKind() == Kind.IDENTIFIER) {
201
                                typeName = ((IdentifierTree) ptt.getType()).getName();
202
                            }
203
                        }
204
                        break;
205
                        case ARRAY_TYPE: {
206
                            ArrayTypeTree ptt = ((ArrayTypeTree) variableTree.getType());
207
                            if (ptt.getType() != null && ptt.getType().getKind() == Kind.IDENTIFIER) {
208
                                typeName = ((IdentifierTree) ptt.getType()).getName();
209
                            }
210
                        }
211
                        break;
212
213
                    }
214
                }
215
216
                ExpressionTree initializer = variableTree.getInitializer();
217
                if (typeName != null && initializer != null) {
218
219
                    Name itName = null;
220
                    switch (initializer.getKind()) {
221
                        case NEW_CLASS: {
222
                            ExpressionTree identifier;
223
                            NewClassTree classTree = (NewClassTree) initializer;
224
                            identifier = classTree.getIdentifier();
225
226
                            if (identifier != null) {
227
228
                                switch (identifier.getKind()) {
229
                                    case IDENTIFIER:
230
                                        itName = ((IdentifierTree) identifier).getName();
231
                                        break;
232
                                    case PARAMETERIZED_TYPE: {
233
234
                                        ParameterizedTypeTree ptt = ((ParameterizedTypeTree) identifier);
235
                                        if (ptt.getType() != null && ptt.getType().getKind() == Kind.IDENTIFIER) {
236
                                            itName = ((IdentifierTree) ptt.getType()).getName();
237
                                        }
238
                                    }
239
                                    break;
240
                                }
241
                            }
242
                        }
243
                        break;
244
                        case NEW_ARRAY: {
245
                            NewArrayTree arrayTree = (NewArrayTree) initializer;
246
                            Tree type = arrayTree.getType();
247
                            if (type != null) {
248
                                if (type.getKind().equals(Kind.IDENTIFIER)) {
249
                                    itName = ((IdentifierTree) type).getName();
250
                                }
251
                            }
252
                        }
253
                        break;
254
                    }
255
256
                    if (typeName.equals(itName)) {
257
                        return Collections.<Fix>emptyList();
258
                    }
259
                }
260
            }
261
            break;
262
263
        }
264
265
        String simpleOrQualifiedName = null;
266
267
        // XXX somewhat crude; is there a simpler way?
268
        TreePath p = path;
269
        while (p != null) {
270
            TreePath parent = p.getParentPath();
271
            if (parent == null) {
272
                break;
273
            }
274
            Kind parentKind = parent.getLeaf().getKind();
275
            if (parentKind == Kind.IMPORT) {
276
                simpleOrQualifiedName = p.getLeaf().toString();
277
                break;
278
            } else if (parentKind == Kind.MEMBER_SELECT || parentKind == Kind.IDENTIFIER) {
279
                p = parent;
280
            } else {
281
                break;
282
            }
283
        }
284
285
        if (simpleOrQualifiedName == null) {
286
            try {
287
                Token<?> ident = findUnresolvedElementToken(info, offset);
288
                if (ident == null) {
289
                    return Collections.<Fix>emptyList();
290
                }
291
                simpleOrQualifiedName = ident.text().toString();
292
            } catch (IOException e) {
293
                Exceptions.printStackTrace(e);
294
                return Collections.<Fix>emptyList();
295
            }
296
        }
297
298
        //copyed from ImportClass-end
299
        if (cancel.get()) {
300
            return Collections.<Fix>emptyList();
301
        }
302
        //#212331 star static imports need to be stripped of the .* part. 
303
        if (simpleOrQualifiedName.endsWith(".*")) {
304
            simpleOrQualifiedName = simpleOrQualifiedName.substring(0, simpleOrQualifiedName.length() - ".*".length());
305
        }
306
307
        List<Fix> fixes = new ArrayList<Fix>();
308
        fixes.add(new OpenDependencyDialogFix(nbModuleProject, simpleOrQualifiedName));
309
        return fixes;
310
    }
311
312
    //copyed from ImportClass
313
    private static Token findUnresolvedElementToken(CompilationInfo info, int offset) throws IOException {
314
        TokenHierarchy<?> th = info.getTokenHierarchy();
315
        TokenSequence<JavaTokenId> ts = th.tokenSequence(JavaTokenId.language());
316
317
        if (ts == null) {
318
            return null;
319
        }
320
321
        ts.move(offset);
322
        if (ts.moveNext()) {
323
            Token t = ts.token();
324
325
            if (t.id() == JavaTokenId.DOT) {
326
                ts.moveNext();
327
                t = ts.token();
328
            } else {
329
                if (t.id() == JavaTokenId.LT) {
330
                    ts.moveNext();
331
                    t = ts.token();
332
                } else {
333
                    if (t.id() == JavaTokenId.NEW) {
334
                        boolean cont = ts.moveNext();
335
336
                        while (cont && ts.token().id() == JavaTokenId.WHITESPACE) {
337
                            cont = ts.moveNext();
338
                        }
339
340
                        if (!cont) {
341
                            return null;
342
                        }
343
                        t = ts.token();
344
                    }
345
                }
346
            }
347
348
            if (t.id() == JavaTokenId.IDENTIFIER) {
349
                return ts.offsetToken();
350
            }
351
        }
352
        return null;
353
    }
354
355
    @Override
356
    public String getId() {
357
        return "NBM_MISSING_CLASS_NBMANT";//NOI18N
358
    }
359
360
    
361
    @Override
362
    public String getDisplayName() {
363
        return NbBundle.getMessage(SearchModuleDependency.class, "LBL_Module_Dependency_Search_DisplayName");
364
    }
365
366
    @Override
367
    public void cancel() {
368
        //cancel task
369
        cancel.set(true);
370
    }
371
372
    static final class OpenDependencyDialogFix implements EnhancedFix {
373
374
        private NbModuleProject project;
375
        private String clazz;
376
377
        public OpenDependencyDialogFix(NbModuleProject project, String clazz) {
378
            this.project = project;
379
            this.clazz = clazz;
380
        }
381
382
        @Override
383
        public CharSequence getSortText() {
384
            return getText();
385
        }
386
387
        @Override
388
        public String getText() {
389
            return NbBundle.getMessage(OpenDependencyDialogFix.class, "FIX_Module_Dependency_Search", clazz);
390
        }
391
392
        @Override
393
        public ChangeInfo implement() throws Exception {
394
            SingleModuleProperties props = SingleModuleProperties.getInstance(project);
395
            final ModuleDependency[] newDeps = AddModulePanel.selectDependencies(props, clazz);
396
            final AtomicBoolean cancel = new AtomicBoolean();
397
            ProgressUtils.runOffEventDispatchThread(new Runnable() {
398
                public @Override
399
                void run() {
400
                    ProjectXMLManager pxm = new ProjectXMLManager(project);
401
                    try {
402
                        pxm.addDependencies(new HashSet<ModuleDependency>(Arrays.asList(newDeps))); // XXX cannot cancel
403
                        ProjectManager.getDefault().saveProject(project);
404
                    } catch (IOException e) {
405
//                        LOG.log(Level.INFO, "Cannot add selected dependencies: " + Arrays.asList(newDeps), e);
406
                    } catch (ProjectXMLManager.CyclicDependencyException ex) {
407
                        NotifyDescriptor.Message msg = new NotifyDescriptor.Message(ex.getLocalizedMessage(), NotifyDescriptor.WARNING_MESSAGE);
408
                        DialogDisplayer.getDefault().notify(msg);
409
                    }
410
                }
411
            }, NbBundle.getMessage(SearchModuleDependency.class, "FIX_Module_Dependency_UpdatingDependencies"), cancel, false);
412
            return null;
413
        }
414
    }
415
}
(-)apisupport.ant/src/org/netbeans/modules/apisupport/project/resources/layer.xml (+7 lines)
Lines 249-252 Link Here
249
            </folder>
249
            </folder>
250
        </folder>
250
        </folder>
251
    </folder>
251
    </folder>
252
    <folder name="org-netbeans-modules-java-hints">
253
        <folder name="rules">
254
            <folder name="errors">
255
                <file name="org-netbeans-modules-apisupport-project-java-hints-errors-SearchModuleDependency.instance"/>
256
            </folder>
257
        </folder>
258
    </folder>
252
</filesystem>
259
</filesystem>
(-)apisupport.ant/src/org/netbeans/modules/apisupport/project/ui/customizer/AddModulePanel.java (-3 / +28 lines)
Lines 40-46 Link Here
40
 * However, if you add GPL Version 2 code and therefore, elected the GPL
40
 * However, if you add GPL Version 2 code and therefore, elected the GPL
41
 * Version 2 license, then the option applies only if the new code is
41
 * Version 2 license, then the option applies only if the new code is
42
 * made subject to such option by the copyright holder.
42
 * made subject to such option by the copyright holder.
43
 */
43
 * 
44
 * Portions Copyrighted 2013 markiewb@netbeans.org
45
*/
44
46
45
package org.netbeans.modules.apisupport.project.ui.customizer;
47
package org.netbeans.modules.apisupport.project.ui.customizer;
46
48
Lines 103-109 Link Here
103
    private Timer timer;
105
    private Timer timer;
104
    
106
    
105
    public static ModuleDependency[] selectDependencies(final SingleModuleProperties props) {
107
    public static ModuleDependency[] selectDependencies(final SingleModuleProperties props) {
106
        final AddModulePanel addPanel = new AddModulePanel(props);
108
        // keep backwards compatibility
109
        return selectDependencies(props, null);
110
    }
111
112
    /**
113
     * 
114
     * @param props
115
     * @param initialFilterText initial filter text or null if not given
116
     * @return 
117
     */
118
    public static ModuleDependency[] selectDependencies(final SingleModuleProperties props, final String initialFilterText) {
119
        final AddModulePanel addPanel;
120
        if (null != initialFilterText) {
121
            // init dialog with filter text
122
            addPanel = new AddModulePanel(props, initialFilterText);
123
        }
124
        else{
125
            // keep backwards compatibility
126
            addPanel = new AddModulePanel(props);
127
        }
107
        final DialogDescriptor descriptor = new DialogDescriptor(addPanel,
128
        final DialogDescriptor descriptor = new DialogDescriptor(addPanel,
108
                getMessage("CTL_AddModuleDependencyTitle"));
129
                getMessage("CTL_AddModuleDependencyTitle"));
109
        descriptor.setHelpCtx(new HelpCtx("org.netbeans.modules.apisupport.project.ui.customizer.AddModulePanel"));
130
        descriptor.setHelpCtx(new HelpCtx("org.netbeans.modules.apisupport.project.ui.customizer.AddModulePanel"));
Lines 132-141 Link Here
132
    }
153
    }
133
    
154
    
134
    public AddModulePanel(final SingleModuleProperties props) {
155
    public AddModulePanel(final SingleModuleProperties props) {
156
        this(props, FILTER_DESCRIPTION);
157
    }
158
159
    private AddModulePanel(final SingleModuleProperties props, String initialString) {
135
        this.props = props;
160
        this.props = props;
136
        initComponents();
161
        initComponents();
137
        initAccessibility();
162
        initAccessibility();
138
        filterValue.setText(FILTER_DESCRIPTION);
163
        filterValue.setText(initialString);
139
        fillUpUniverseModules();
164
        fillUpUniverseModules();
140
        moduleList.setCellRenderer(CustomizerComponentFactory.getDependencyCellRenderer(false));
165
        moduleList.setCellRenderer(CustomizerComponentFactory.getDependencyCellRenderer(false));
141
        moduleList.addListSelectionListener(new ListSelectionListener() {
166
        moduleList.addListSelectionListener(new ListSelectionListener() {
(-)java.hints.legacy.spi/nbproject/project.xml (+1 lines)
Lines 97-102 Link Here
97
                </dependency>
97
                </dependency>
98
            </module-dependencies>
98
            </module-dependencies>
99
            <friend-packages>
99
            <friend-packages>
100
                <friend>org.netbeans.modules.apisupport.ant</friend>
100
                <friend>org.netbeans.modules.javadoc</friend>
101
                <friend>org.netbeans.modules.javadoc</friend>
101
                <friend>org.netbeans.modules.javahints</friend>
102
                <friend>org.netbeans.modules.javahints</friend>
102
                <friend>org.netbeans.modules.maven.hints</friend>
103
                <friend>org.netbeans.modules.maven.hints</friend>

Return to bug 212656