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

(-)a/java.hints/src/org/netbeans/modules/java/hints/infrastructure/ErrorHintsProvider.java (-4 / +30 lines)
Lines 85-90 Link Here
85
import org.netbeans.api.lexer.Token;
85
import org.netbeans.api.lexer.Token;
86
import org.netbeans.api.lexer.TokenHierarchy;
86
import org.netbeans.api.lexer.TokenHierarchy;
87
import org.netbeans.api.lexer.TokenSequence;
87
import org.netbeans.api.lexer.TokenSequence;
88
import org.netbeans.modules.editor.NbEditorDocument;
88
import org.netbeans.modules.editor.java.Utilities;
89
import org.netbeans.modules.editor.java.Utilities;
89
import org.netbeans.modules.java.hints.spi.ErrorRule;
90
import org.netbeans.modules.java.hints.spi.ErrorRule;
90
import org.netbeans.modules.java.hints.spi.ErrorRule.Data;
91
import org.netbeans.modules.java.hints.spi.ErrorRule.Data;
Lines 93-98 Link Here
93
import org.netbeans.spi.editor.hints.HintsController;
94
import org.netbeans.spi.editor.hints.HintsController;
94
import org.openide.cookies.LineCookie;
95
import org.openide.cookies.LineCookie;
95
import org.openide.text.NbDocument;
96
import org.openide.text.NbDocument;
97
import org.openide.util.Exceptions;
96
98
97
99
98
100
Lines 119-126 Link Here
119
        errorKind2Severity.put(Diagnostic.Kind.NOTE, Severity.WARNING);
121
        errorKind2Severity.put(Diagnostic.Kind.NOTE, Severity.WARNING);
120
        errorKind2Severity.put(Diagnostic.Kind.OTHER, Severity.WARNING);
122
        errorKind2Severity.put(Diagnostic.Kind.OTHER, Severity.WARNING);
121
    }
123
    }
124
125
    /**
126
     * @return errors for whole file
127
     */
128
    List<ErrorDescription> computeErrors(CompilationInfo info, Document doc) throws IOException {
129
        return computeErrors(info, doc, null);
130
    }
122
    
131
    
123
    List<ErrorDescription> computeErrors(CompilationInfo info, Document doc) throws IOException {
132
    /**
133
     * @param forPosition position for ehich errors would be computed
134
     * @return errors for line specified by forPosition
135
     * @throws IOException
136
     */
137
    List<ErrorDescription> computeErrors(CompilationInfo info, Document doc, Integer forPosition) throws IOException {
124
        List<Diagnostic> errors = info.getDiagnostics();
138
        List<Diagnostic> errors = info.getDiagnostics();
125
        List<ErrorDescription> descs = new ArrayList<ErrorDescription>();
139
        List<ErrorDescription> descs = new ArrayList<ErrorDescription>();
126
        
140
        
Lines 128-134 Link Here
128
            ERR.log(ErrorManager.INFORMATIONAL, "errors = " + errors );
142
            ERR.log(ErrorManager.INFORMATIONAL, "errors = " + errors );
129
        
143
        
130
        Map<Class, Data> data = new HashMap<Class, Data>();
144
        Map<Class, Data> data = new HashMap<Class, Data>();
131
        
145
132
        for (Diagnostic d : errors) {
146
        for (Diagnostic d : errors) {
133
            if (isCanceled())
147
            if (isCanceled())
134
                return null;
148
                return null;
Lines 162-174 Link Here
162
            
176
            
163
            final String desc = d.getMessage(null);
177
            final String desc = d.getMessage(null);
164
            final Position[] range = getLine(info, d, doc, (int)d.getStartPosition(), (int)d.getEndPosition());
178
            final Position[] range = getLine(info, d, doc, (int)d.getStartPosition(), (int)d.getEndPosition());
165
            
179
166
            if (isCanceled())
180
            if (isCanceled())
167
                return null;
181
                return null;
168
            
182
            
169
            if (range[0] == null || range[1] == null)
183
            if (range[0] == null || range[1] == null)
170
                continue;
184
                continue;
171
185
186
            if (forPosition != null) {
187
                try {
188
                    int posRowStart = org.netbeans.editor.Utilities.getRowStart((NbEditorDocument) doc, forPosition);
189
                    int errRowStart = org.netbeans.editor.Utilities.getRowStart((NbEditorDocument) doc, range[0].getOffset());
190
                    if (posRowStart != errRowStart) {
191
                        continue;
192
                    }
193
                } catch (BadLocationException ex) {
194
                    Exceptions.printStackTrace(ex);
195
                }
196
            }
197
            
172
            descs.add(ErrorDescriptionFactory.createErrorDescription(errorKind2Severity.get(d.getKind()), desc, ehm, doc, range[0], range[1]));
198
            descs.add(ErrorDescriptionFactory.createErrorDescription(errorKind2Severity.get(d.getKind()), desc, ehm, doc, range[0], range[1]));
173
        }
199
        }
174
        
200
        
Lines 477-483 Link Here
477
            if (errors == null) //meaning: cancelled
503
            if (errors == null) //meaning: cancelled
478
                return ;
504
                return ;
479
505
480
            HintsController.setErrors(doc, "java-hints", errors);
506
            HintsController.setErrors(doc, ErrorHintsProvider.class.getName(), errors);
481
            
507
            
482
            long end = System.currentTimeMillis();
508
            long end = System.currentTimeMillis();
483
509
(-)a/java.hints/src/org/netbeans/modules/java/hints/infrastructure/HintsTask.java (-2 / +2 lines)
Lines 92-98 Link Here
92
    private Map<Kind, List<TreeRule>> presetHints;
92
    private Map<Kind, List<TreeRule>> presetHints;
93
    
93
    
94
    public HintsTask() {}
94
    public HintsTask() {}
95
    
95
96
    public HintsTask(List<TreeRule> hints) {
96
    public HintsTask(List<TreeRule> hints) {
97
        presetHints = new  EnumMap<Kind, List<TreeRule>>(Kind.class);
97
        presetHints = new  EnumMap<Kind, List<TreeRule>>(Kind.class);
98
        
98
        
Lines 113-119 Link Here
113
        return computeHints(info, new TreePath(info.getCompilationUnit()));
113
        return computeHints(info, new TreePath(info.getCompilationUnit()));
114
    }
114
    }
115
    
115
    
116
    private List<ErrorDescription> computeHints(CompilationInfo info, TreePath startAt) {
116
    public List<ErrorDescription> computeHints(CompilationInfo info, TreePath startAt) {
117
        Map<Kind, List<TreeRule>> hints = presetHints != null ? presetHints : RulesManager.getInstance().getHints(false);
117
        Map<Kind, List<TreeRule>> hints = presetHints != null ? presetHints : RulesManager.getInstance().getHints(false);
118
        
118
        
119
        if (hints.isEmpty()) {
119
        if (hints.isEmpty()) {
(-)1436de250f92 (+146 lines)
Added 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.hints.infrastructure;
41
42
import com.sun.source.tree.Tree;
43
import com.sun.source.util.TreePath;
44
import java.io.IOException;
45
import java.util.ArrayList;
46
import java.util.HashMap;
47
import java.util.HashSet;
48
import java.util.List;
49
import java.util.Map;
50
import java.util.Set;
51
import javax.swing.text.Document;
52
import org.netbeans.api.java.source.CompilationController;
53
import org.netbeans.api.java.source.JavaSource;
54
import org.netbeans.api.java.source.Task;
55
import org.netbeans.editor.BaseDocument;
56
import org.netbeans.editor.Utilities;
57
import org.netbeans.spi.editor.hints.Context;
58
import org.netbeans.spi.editor.hints.ErrorDescription;
59
import org.netbeans.spi.editor.hints.LazyFixList;
60
import org.netbeans.spi.editor.hints.PositionRefresher;
61
import org.openide.util.Exceptions;
62
63
/**
64
 * Refreshes all Java Hints on current line upon Alt-Enter or mouseclick
65
 * @author Max Sauer
66
 */
67
public class JavaHintsPositionRefresher implements PositionRefresher {
68
69
    public Map<String, List<ErrorDescription>> getErrorDescriptionsAt(Context context, Document doc) {
70
        JavaSource js = JavaSource.forDocument(doc);
71
        final Map<String, List<ErrorDescription>> eds = new HashMap<String, List<ErrorDescription>>();
72
        
73
        try {
74
            js.runUserActionTask(new RefreshTask(eds, context, doc), true);
75
        } catch (IOException ex) {
76
            Exceptions.printStackTrace(ex);
77
        }
78
79
        return eds;
80
    }
81
82
83
    private class RefreshTask implements Task<CompilationController> {
84
85
        private final Map<String, List<ErrorDescription>> eds;
86
        private final Context ctx;
87
        private final Document doc;
88
89
        public RefreshTask( Map<String, List<ErrorDescription>> eds, Context ctx, Document doc) {
90
            this.eds = eds;
91
            this.ctx = ctx;
92
            this.doc = doc;
93
        }
94
95
        public void run(CompilationController controller) throws Exception {
96
            controller.toPhase(JavaSource.Phase.RESOLVED);
97
            int position = ctx.getPosition();
98
99
            //TODO: better cancel handling (propagate into tasks?)
100
            if (ctx.isCanceled()) {
101
                return;
102
            }
103
104
            //SuggestionsTask
105
            SuggestionsTask suggestionsTask = new SuggestionsTask();
106
            suggestionsTask.run(controller);
107
            eds.put(SuggestionsTask.class.getName(), suggestionsTask.getSuggestions());
108
109
            if (ctx.isCanceled()) {
110
                return;
111
            }
112
            
113
            //HintsTask
114
            int rowStart = Utilities.getRowStart((BaseDocument) doc, position);
115
            int rowEnd = Utilities.getRowEnd((BaseDocument) doc, position);
116
            Set<ErrorDescription> errs = new HashSet<ErrorDescription>();
117
            Set<Tree> encounteredLeafs = new HashSet<Tree>();
118
            HintsTask task = new HintsTask();
119
            for (int i = rowStart; i < rowEnd; i++) {
120
                TreePath path = controller.getTreeUtilities().pathFor(i);
121
                Tree leaf = path.getLeaf();
122
                if (!encounteredLeafs.contains(leaf)) {
123
                    errs.addAll(task.computeHints(controller, path));
124
                    encounteredLeafs.add(leaf);
125
                }
126
            }
127
            
128
            eds.put(HintsTask.class.getName(), new ArrayList<ErrorDescription>(errs));
129
130
            if (ctx.isCanceled()) {
131
                return;
132
            }
133
134
            //ErrorHints
135
            final List<ErrorDescription> errors = new ErrorHintsProvider().computeErrors(controller, doc, position);
136
            for (ErrorDescription ed : errors) {
137
                LazyFixList fixes = ed.getFixes();
138
                if (fixes instanceof CreatorBasedLazyFixList) { //compute fixes, since they're lazy computed
139
                    ((CreatorBasedLazyFixList) ed.getFixes()).compute(controller, ctx.getCancel());
140
                }
141
            }
142
            eds.put(ErrorHintsProvider.class.getName(), errors);
143
        }
144
145
    }
146
}
(-)a/java.hints/src/org/netbeans/modules/java/hints/infrastructure/SuggestionsTask.java (-2 / +8 lines)
Lines 63-70 Link Here
63
 * @author Jan Lahoda
63
 * @author Jan Lahoda
64
 */
64
 */
65
public class SuggestionsTask extends ScanningCancellableTask<CompilationInfo> {
65
public class SuggestionsTask extends ScanningCancellableTask<CompilationInfo> {
66
67
    private final List<ErrorDescription> result;
66
    
68
    
67
    public SuggestionsTask() {
69
    public SuggestionsTask() {
70
        result = new ArrayList<ErrorDescription>();
68
    }
71
    }
69
    
72
    
70
    public void run(CompilationInfo info) throws Exception {
73
    public void run(CompilationInfo info) throws Exception {
Lines 95-101 Link Here
95
        }
98
        }
96
        
99
        
97
        int position = CaretAwareJavaSourceTaskFactory.getLastPosition(info.getFileObject());
100
        int position = CaretAwareJavaSourceTaskFactory.getLastPosition(info.getFileObject());
98
        List<ErrorDescription> result = new ArrayList<ErrorDescription>();
99
        
101
        
100
        if (position != (-1)) {
102
        if (position != (-1)) {
101
            TreePath tp = info.getTreeUtilities().pathFor(position);
103
            TreePath tp = info.getTreeUtilities().pathFor(position);
Lines 137-141 Link Here
137
        
139
        
138
        HintsController.setErrors(info.getFileObject(), SuggestionsTask.class.getName(), result);
140
        HintsController.setErrors(info.getFileObject(), SuggestionsTask.class.getName(), result);
139
    }
141
    }
140
    
142
143
    public List<ErrorDescription> getSuggestions() {
144
        return result;
145
    }
146
141
}
147
}
(-)a/java.hints/src/org/netbeans/modules/java/hints/resources/layer.xml (+1 lines)
Lines 94-99 Link Here
94
                    <file name="org-netbeans-modules-java-hints-infrastructure-JavaUpToDateStateProviderFactory.instance"/>
94
                    <file name="org-netbeans-modules-java-hints-infrastructure-JavaUpToDateStateProviderFactory.instance"/>
95
                </folder>
95
                </folder>
96
                <file name="org-netbeans-modules-java-hints-infrastructure-ErrorHintsFactory.instance" />
96
                <file name="org-netbeans-modules-java-hints-infrastructure-ErrorHintsFactory.instance" />
97
                <file name="org-netbeans-modules-java-hints-infrastructure-JavaHintsPositionRefresher.instance"/>
97
            </folder>
98
            </folder>
98
        </folder>
99
        </folder>
99
    </folder>
100
    </folder>
(-)1436de250f92 (+197 lines)
Added 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.hints.infrastructure;
41
42
import java.io.File;
43
import java.lang.reflect.Constructor;
44
import java.util.List;
45
import java.util.Map;
46
import java.util.Map.Entry;
47
import java.util.concurrent.atomic.AtomicBoolean;
48
import javax.swing.text.Document;
49
import org.netbeans.api.editor.mimelookup.MimePath;
50
import org.netbeans.api.java.lexer.JavaTokenId;
51
import org.netbeans.api.java.source.CompilationInfo;
52
import org.netbeans.api.java.source.JavaSource;
53
import org.netbeans.api.java.source.JavaSource.Phase;
54
import org.netbeans.api.java.source.SourceUtilsTestUtil;
55
import org.netbeans.api.java.source.TestUtilities;
56
import org.netbeans.api.lexer.InputAttributes;
57
import org.netbeans.api.lexer.Language;
58
import org.netbeans.api.lexer.LanguagePath;
59
import org.netbeans.api.lexer.Token;
60
import static org.junit.Assert.*;
61
import org.netbeans.junit.NbTestCase;
62
import org.netbeans.modules.editor.java.JavaKit;
63
import org.netbeans.modules.java.JavaDataLoader;
64
import org.netbeans.modules.parsing.api.indexing.IndexingManager;
65
import org.netbeans.spi.editor.hints.Context;
66
import org.netbeans.spi.editor.hints.ErrorDescription;
67
import org.netbeans.spi.editor.hints.PositionRefresher;
68
import org.netbeans.spi.editor.mimelookup.MimeDataProvider;
69
import org.netbeans.spi.lexer.LanguageEmbedding;
70
import org.netbeans.spi.lexer.LanguageProvider;
71
import org.openide.cookies.EditorCookie;
72
import org.openide.filesystems.FileObject;
73
import org.openide.filesystems.FileUtil;
74
import org.openide.loaders.DataObject;
75
import org.openide.util.Lookup;
76
import org.openide.util.lookup.Lookups;
77
78
/**
79
 * Test class for JavaHints implementation of Editor Hints {@link PositionRefresher}
80
 * @author Max Sauer
81
 */
82
public class JavaHintsPositionRefresherTest extends NbTestCase {
83
84
    private FileObject sourceRoot;
85
    private CompilationInfo info;
86
    private Document doc;
87
88
    public JavaHintsPositionRefresherTest(String name) {
89
        super(name);
90
    }
91
92
93
    @Override
94
    public void setUp() throws Exception {
95
        super.setUp();
96
        SourceUtilsTestUtil.prepareTest(new String[]{"org/netbeans/modules/java/editor/resources/layer.xml"},
97
                new Object[]{JavaDataLoader.class,
98
                new MimeDataProvider() {
99
                public Lookup getLookup(MimePath mimePath) {
100
                    return Lookups.fixed(new Object[] {
101
                        new JavaKit(),
102
                    });
103
                }
104
            },
105
            new LanguageProvider() {
106
                public Language<?> findLanguage(String mimePath) {
107
                    return JavaTokenId.language();
108
                }
109
110
                public LanguageEmbedding<?> findLanguageEmbedding(Token<?> token,
111
                        LanguagePath languagePath,
112
                        InputAttributes inputAttributes) {
113
                    return null;
114
                }
115
            }
116
        });
117
    }
118
119
    private void prepareTest(String fileName, String code) throws Exception {
120
        clearWorkDir();
121
122
        FileObject workFO = FileUtil.toFileObject(getWorkDir());
123
124
        assertNotNull(workFO);
125
126
        sourceRoot = workFO.createFolder("src");
127
128
        FileObject buildRoot  = workFO.createFolder("build");
129
        FileObject cache = workFO.createFolder("cache");
130
131
        FileObject data = FileUtil.createData(sourceRoot, fileName);
132
        File dataFile = FileUtil.toFile(data);
133
134
        assertNotNull(dataFile);
135
136
        TestUtilities.copyStringToFile(dataFile, code);
137
138
//        SourceUtilsTestUtil.prepareTest(new String[0], new Object[]{
139
//                    new JavaCustomIndexer.Factory()});
140
        SourceUtilsTestUtil.prepareTest(sourceRoot, buildRoot, cache);
141
142
        DataObject od = DataObject.find(data);
143
        EditorCookie ec = od.getCookie(EditorCookie.class);
144
145
        assertNotNull(ec);
146
147
        doc = ec.openDocument();
148
        doc.putProperty(Language.class, JavaTokenId.language());
149
        doc.putProperty("mimeType", "text/x-java");
150
151
        //XXX: takes a long time
152
        //re-index, in order to find classes-living-elsewhere
153
        IndexingManager.getDefault().refreshIndexAndWait(sourceRoot.getURL(), null);
154
155
        JavaSource js = JavaSource.forFileObject(data);
156
157
        assertNotNull(js);
158
159
        info = SourceUtilsTestUtil.getCompilationInfo(js, Phase.RESOLVED);
160
161
        assertNotNull(info);
162
    }
163
164
    private Context prepareContext(int position) {
165
        Context ctx = null;
166
        try {
167
            Constructor constructor = Context.class.getDeclaredConstructor(int.class, AtomicBoolean.class);
168
            constructor.setAccessible(true);
169
            ctx = (Context) constructor.newInstance(new Integer(position), new AtomicBoolean());
170
        } catch (Exception ex) {
171
            ex.printStackTrace();
172
        }
173
        return ctx;
174
    }
175
176
    public void testErrorHint0() throws Exception {
177
        performTest("test/Test.java", "package test; public class Test {public void foo() {\n| new Foo();}}", "1:0-1:14:error:illegal start of expression1:6-1:9:error:cannot find symbol\n  symbol  : class Foo\n  location: class test.Test");
178
    }
179
180
    private void performTest(String fileName , String code, String expected) throws Exception {
181
        prepareTest(fileName, code);
182
        int[] caretPosition = new int[1];
183
        code = org.netbeans.modules.java.hints.TestUtilities.detectOffsets(code, caretPosition);
184
        Context ctx = prepareContext(caretPosition[0]);
185
        Map<String, List<ErrorDescription>> errorDescriptionsAt = new JavaHintsPositionRefresher().getErrorDescriptionsAt(ctx, doc);
186
        StringBuffer buf = new StringBuffer();
187
        for (Entry<String, List<ErrorDescription>> e : errorDescriptionsAt.entrySet()) {
188
            for (ErrorDescription ed : e.getValue()) {
189
                buf.append(ed.toString());
190
            }
191
192
        }
193
        assertEquals("Provided error messages differ. ", expected, buf.toString());
194
    }
195
   
196
197
}
(-)a/spi.editor.hints/apichanges.xml (-1 / +13 lines)
Lines 105-111 Link Here
105
105
106
    <changes>
106
    <changes>
107
107
108
        <!-- Start here... -->
108
        <change id="Refreshers">
109
             <api name="editor.hints"/>
110
             <summary>Added PositionRefresher interface and Context</summary>
111
             <version major="1" minor="8" subsubminor="1"/>
112
             <date day="20" month="7" year="2009"/>
113
             <author login="msauer"/>
114
             <compatibility addition="yes" binary="compatible" deletion="no" deprecation="no" modification="no" semantic="compatible" source="compatible"/>
115
             <description>
116
                 Added new interface and context class in order to be able to provide up-to-date hints on current line.
117
             </description>
118
             <class name="PositionRefresher" package="org.netbeans.spi.editor.hints"/>
119
             <class name="Context" package="org.netbeans.spi.editor.hints"/>
120
        </change>
109
121
110
    </changes>
122
    </changes>
111
123
(-)a/spi.editor.hints/nbproject/project.properties (-1 / +1 lines)
Lines 39-42 Link Here
39
javac.compilerargs=-Xlint:unchecked
39
javac.compilerargs=-Xlint:unchecked
40
javac.source=1.5
40
javac.source=1.5
41
javadoc.arch=${basedir}/arch.xml
41
javadoc.arch=${basedir}/arch.xml
42
spec.version.base=1.8.0
42
spec.version.base=1.8.1
(-)a/spi.editor.hints/src/org/netbeans/modules/editor/hints/AnnotationHolder.java (-1 / +31 lines)
Lines 61-66 Link Here
61
import java.util.LinkedList;
61
import java.util.LinkedList;
62
import java.util.List;
62
import java.util.List;
63
import java.util.Map;
63
import java.util.Map;
64
import java.util.Map.Entry;
64
import java.util.Set;
65
import java.util.Set;
65
import java.util.SortedMap;
66
import java.util.SortedMap;
66
import java.util.TreeMap;
67
import java.util.TreeMap;
Lines 660-666 Link Here
660
            detachAnnotation(previous);
661
            detachAnnotation(previous);
661
        }
662
        }
662
663
663
        attachAnnotation(line, pea);
664
        attachAnnotation(line, pea);   
664
    }
665
    }
665
666
666
    void updateHighlightsOnLine(Position line) throws IOException {
667
    void updateHighlightsOnLine(Position line) throws IOException {
Lines 998-1003 Link Here
998
        return new ArrayList<Annotation>(line2Annotations.values());
999
        return new ArrayList<Annotation>(line2Annotations.values());
999
    }
1000
    }
1000
1001
1002
    public void setErrorsForLine(final int offset, final Map<String, List<ErrorDescription>> errs) {
1003
1004
        doc.render(new Runnable() {
1005
1006
            public void run() {
1007
                try {
1008
                    Position pos = getPosition(Utilities.getLineOffset(doc, offset), true);
1009
1010
                    List<ErrorDescription> errsForCurrentLine = getErrorsForLine(pos, true);
1011
1012
                    //for each layer
1013
                    for (Entry<String, List<ErrorDescription>> e : errs.entrySet()) {
1014
                        //get errors for this layer, all lines
1015
                        Set<ErrorDescription> errorsForLayer = new HashSet<ErrorDescription>(getErrorsForLayer(e.getKey()));
1016
                        errorsForLayer.removeAll(errsForCurrentLine); //remove all for current line
1017
                        e.getValue().addAll(errorsForLayer); //add the rest to those provided by refresher
1018
                    }
1019
                } catch (BadLocationException ex) {
1020
                    Exceptions.printStackTrace(ex);
1021
                }
1022
            }
1023
        });
1024
1025
        for (Entry<String, List<ErrorDescription>> e : errs.entrySet()) {
1026
            final List<ErrorDescription> eds = e.getValue();
1027
            setErrorDescriptions(e.getKey(), eds); //set updated
1028
        }
1029
    }
1030
1001
    public synchronized List<ErrorDescription> getErrorsGE(int offset) {
1031
    public synchronized List<ErrorDescription> getErrorsGE(int offset) {
1002
        try {
1032
        try {
1003
            Position current = null;
1033
            Position current = null;
(-)1436de250f92 (+69 lines)
Added 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.editor.hints;
40
41
import java.util.concurrent.atomic.AtomicBoolean;
42
import org.netbeans.spi.editor.hints.Context;
43
44
/**
45
 * Accessor for {@link Context}'s package private constructor
46
 * @author Max Sauer
47
 */
48
public abstract class ContextAccessor {
49
50
    public static ContextAccessor DEFAULT;
51
52
    public static ContextAccessor getDefault() {
53
        if (DEFAULT != null) {
54
            return DEFAULT;
55
        }
56
57
        Class c = Context.class;
58
        try {
59
            Class.forName(c.getName(), true, c.getClassLoader());
60
        } catch (ClassNotFoundException ex) {
61
            assert false : ex;
62
        }
63
64
        assert DEFAULT != null;
65
        return DEFAULT;
66
    }
67
68
    public abstract Context newContext(int position, AtomicBoolean cancel);
69
}
(-)a/spi.editor.hints/src/org/netbeans/modules/editor/hints/HintsUI.java (-11 / +52 lines)
Lines 41-47 Link Here
41
41
42
package org.netbeans.modules.editor.hints;
42
package org.netbeans.modules.editor.hints;
43
43
44
import java.awt.*;
44
import java.awt.AWTEvent;
45
import java.awt.Color;
46
import java.awt.Component;
47
import java.awt.Container;
48
import java.awt.Cursor;
49
import java.awt.Dimension;
50
import java.awt.HeadlessException;
51
import java.awt.Point;
52
import java.awt.Rectangle;
53
import java.awt.Toolkit;
45
import java.awt.event.AWTEventListener;
54
import java.awt.event.AWTEventListener;
46
import java.awt.event.KeyEvent;
55
import java.awt.event.KeyEvent;
47
import java.awt.event.KeyListener;
56
import java.awt.event.KeyListener;
Lines 53-58 Link Here
53
import java.io.IOException;
62
import java.io.IOException;
54
import java.lang.ref.Reference;
63
import java.lang.ref.Reference;
55
import java.lang.ref.WeakReference;
64
import java.lang.ref.WeakReference;
65
import java.util.Collection;
66
import java.util.List;
67
import java.util.Map;
68
import java.util.concurrent.atomic.AtomicBoolean;
56
import java.util.logging.Level;
69
import java.util.logging.Level;
57
import java.util.logging.LogRecord;
70
import java.util.logging.LogRecord;
58
import java.util.logging.Logger;
71
import java.util.logging.Logger;
Lines 62-67 Link Here
62
import javax.swing.text.JTextComponent;
75
import javax.swing.text.JTextComponent;
63
import javax.swing.text.Position;
76
import javax.swing.text.Position;
64
import org.netbeans.api.editor.EditorRegistry;
77
import org.netbeans.api.editor.EditorRegistry;
78
import org.netbeans.api.editor.mimelookup.MimeLookup;
65
import org.netbeans.editor.AnnotationDesc;
79
import org.netbeans.editor.AnnotationDesc;
66
import org.netbeans.editor.Annotations;
80
import org.netbeans.editor.Annotations;
67
import org.netbeans.editor.BaseDocument;
81
import org.netbeans.editor.BaseDocument;
Lines 71-77 Link Here
71
import org.netbeans.modules.editor.hints.borrowed.ListCompletionView;
85
import org.netbeans.modules.editor.hints.borrowed.ListCompletionView;
72
import org.netbeans.modules.editor.hints.borrowed.ScrollCompletionPane;
86
import org.netbeans.modules.editor.hints.borrowed.ScrollCompletionPane;
73
import org.netbeans.spi.editor.hints.ChangeInfo;
87
import org.netbeans.spi.editor.hints.ChangeInfo;
88
import org.netbeans.spi.editor.hints.Context;
89
import org.netbeans.spi.editor.hints.ErrorDescription;
74
import org.netbeans.spi.editor.hints.Fix;
90
import org.netbeans.spi.editor.hints.Fix;
91
import org.netbeans.spi.editor.hints.PositionRefresher;
75
import org.openide.ErrorManager;
92
import org.openide.ErrorManager;
76
import org.openide.cookies.EditCookie;
93
import org.openide.cookies.EditCookie;
77
import org.openide.cookies.EditorCookie;
94
import org.openide.cookies.EditorCookie;
Lines 81-86 Link Here
81
import org.openide.loaders.DataObjectNotFoundException;
98
import org.openide.loaders.DataObjectNotFoundException;
82
import org.openide.text.Annotation;
99
import org.openide.text.Annotation;
83
import org.openide.util.Exceptions;
100
import org.openide.util.Exceptions;
101
import org.openide.util.Lookup;
84
import org.openide.util.NbBundle;
102
import org.openide.util.NbBundle;
85
import org.openide.util.RequestProcessor;
103
import org.openide.util.RequestProcessor;
86
import org.openide.util.Task;
104
import org.openide.util.Task;
Lines 114-124 Link Here
114
    private JLabel hintIcon;
132
    private JLabel hintIcon;
115
    private ScrollCompletionPane hintListComponent;
133
    private ScrollCompletionPane hintListComponent;
116
    private JLabel errorTooltip;
134
    private JLabel errorTooltip;
135
    private AtomicBoolean cancel;
117
    
136
    
118
    /** Creates a new instance of HintsUI */
137
    /** Creates a new instance of HintsUI */
119
    private HintsUI() {
138
    private HintsUI() {
120
        EditorRegistry.addPropertyChangeListener(this);
139
        EditorRegistry.addPropertyChangeListener(this);
121
        propertyChange(null);
140
        propertyChange(null);
141
        cancel = new AtomicBoolean(false);
122
    }
142
    }
123
    
143
    
124
    public JTextComponent getComponent() {
144
    public JTextComponent getComponent() {
Lines 138-143 Link Here
138
            this.compRef = new WeakReference<JTextComponent>(comp);
158
            this.compRef = new WeakReference<JTextComponent>(comp);
139
            register();
159
            register();
140
        }
160
        }
161
    }
162
163
    private AnnotationHolder getAnnotationHolder(Document doc) {
164
        DataObject od = (DataObject) doc.getProperty(Document.StreamDescriptionProperty);
165
        if (od == null) {
166
            return null;
167
        }
168
        return AnnotationHolder.getInstance(od.getPrimaryFile());
141
    }
169
    }
142
170
143
    private void register() {
171
    private void register() {
Lines 422-434 Link Here
422
    }
450
    }
423
    
451
    
424
    private ParseErrorAnnotation findAnnotation(Document doc, AnnotationDesc desc, int lineNum) {
452
    private ParseErrorAnnotation findAnnotation(Document doc, AnnotationDesc desc, int lineNum) {
425
        DataObject od = (DataObject) doc.getProperty(Document.StreamDescriptionProperty);
453
        AnnotationHolder annotations = getAnnotationHolder(doc);
426
        
454
427
        if (od == null)
428
            return null;
429
        
430
        AnnotationHolder annotations = AnnotationHolder.getInstance(od.getPrimaryFile());
431
        
432
        if (annotations != null) {
455
        if (annotations != null) {
433
            for (Annotation a : annotations.getAnnotations()) {
456
            for (Annotation a : annotations.getAnnotations()) {
434
                if (a instanceof ParseErrorAnnotation) {
457
                if (a instanceof ParseErrorAnnotation) {
Lines 444-458 Link Here
444
        
467
        
445
        return null;
468
        return null;
446
    }
469
    }
447
    
470
448
    boolean invokeDefaultAction(boolean onlyActive) {
471
    boolean invokeDefaultAction(boolean onlyActive) {
449
        JTextComponent comp = getComponent(); 
472
        JTextComponent comp = getComponent(); 
450
        if (comp == null) {
473
        if (comp == null) {
451
            Logger.getLogger(HintsUI.class.getName()).log(Level.WARNING, "HintsUI.invokeDefaultAction called, but comp == null");
474
            Logger.getLogger(HintsUI.class.getName()).log(Level.WARNING, "HintsUI.invokeDefaultAction called, but comp == null");
452
            return false;
475
            return false;
453
        }
476
        }
454
        
477
455
        Document doc = comp.getDocument();
478
        Document doc = comp.getDocument();
479
480
        cancel.set(false);
481
        refresh(doc, comp.getCaretPosition());
456
        
482
        
457
        if (doc instanceof BaseDocument) {
483
        if (doc instanceof BaseDocument) {
458
            Annotations annotations = ((BaseDocument) doc).getAnnotations();
484
            Annotations annotations = ((BaseDocument) doc).getAnnotations();
Lines 507-513 Link Here
507
        if (comp == null) {
533
        if (comp == null) {
508
            return;
534
            return;
509
        }
535
        }
510
        boolean bulbShowing = hintIcon != null && hintIcon.isShowing();
536
//        boolean bulbShowing = hintIcon != null && hintIcon.isShowing();
511
        boolean errorTooltipShowing = errorTooltip != null && errorTooltip.isShowing();
537
        boolean errorTooltipShowing = errorTooltip != null && errorTooltip.isShowing();
512
        boolean popupShowing = hintListComponent != null && hintListComponent.isShowing();
538
        boolean popupShowing = hintListComponent != null && hintListComponent.isShowing();
513
        
539
        
Lines 541-546 Link Here
541
        } else if ( e.getKeyCode() == KeyEvent.VK_ESCAPE ) {
567
        } else if ( e.getKeyCode() == KeyEvent.VK_ESCAPE ) {
542
            if ( popupShowing ) {
568
            if ( popupShowing ) {
543
                removePopup();
569
                removePopup();
570
            } else {
571
                //user is tired of waiting for refresh before popup is shown
572
                cancel.set(true);
544
            }
573
            }
545
        } else if ( popupShowing ) {
574
        } else if ( popupShowing ) {
546
            InputMap input = hintListComponent.getInputMap();
575
            InputMap input = hintListComponent.getInputMap();
Lines 712-715 Link Here
712
        return input;
741
        return input;
713
    }
742
    }
714
743
744
    private void refresh(Document doc, int pos) {
745
        Context context = ContextAccessor.getDefault().newContext(pos, cancel);
746
        String mimeType = org.netbeans.lib.editor.util.swing.DocumentUtilities.getMimeType(doc);
747
        Lookup lookup = MimeLookup.getLookup(mimeType);
748
        Collection<? extends PositionRefresher> refreshers = lookup.lookupAll(PositionRefresher.class);
749
        //set errors from all available refreshers
750
        for (PositionRefresher ref : refreshers) {
751
            Map<String, List<ErrorDescription>> layer2Errs = ref.getErrorDescriptionsAt(context, doc);
752
            getAnnotationHolder(doc).setErrorsForLine(pos, layer2Errs);
753
        }
754
    }
755
715
}
756
}
(-)1436de250f92 (+95 lines)
Added 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.spi.editor.hints;
41
42
import java.util.concurrent.atomic.AtomicBoolean;
43
import org.netbeans.modules.editor.hints.ContextAccessor;
44
45
/**
46
 * Context for {@link PositionRefresher}
47
 * Provides position of current alt-enter invocation and its cancel status
48
 * 
49
 * @author Max Sauer
50
 * @since 1.8.1
51
 */
52
public final class Context {
53
54
    final AtomicBoolean cancel;
55
    final int position;
56
57
    Context(int position, AtomicBoolean cancel) {
58
        this.position = position;
59
        this.cancel = cancel;
60
    }
61
62
    /**
63
     * @return true if invocation has been canceled
64
     */
65
    public boolean isCanceled() {
66
        return cancel.get();
67
    }
68
69
    /**
70
     * @return Caret offset inside current document
71
     */
72
    public int getPosition() {
73
        return position;
74
    }
75
76
    /**
77
     * @return cancel status
78
     */
79
    public AtomicBoolean getCancel() {
80
        return cancel;
81
    }
82
83
    static {
84
        ContextAccessor.DEFAULT = new ComtextImpl();
85
    }
86
}
87
88
final class ComtextImpl extends ContextAccessor {
89
90
    @Override
91
    public Context newContext(int position, AtomicBoolean cancel) {
92
        return new Context(position, cancel);
93
    }
94
95
}
(-)a/spi.editor.hints/src/org/netbeans/spi/editor/hints/ErrorDescription.java (-5 / +5 lines)
Lines 53-63 Link Here
53
 */
53
 */
54
public final class ErrorDescription {
54
public final class ErrorDescription {
55
55
56
    private String        description;
56
    private final String description;
57
    private Severity      severity;
57
    private final Severity severity;
58
    private LazyFixList   fixes;
58
    private final LazyFixList fixes;
59
    private PositionBounds span;
59
    private final PositionBounds span;
60
    private FileObject     file;
60
    private final FileObject file;
61
61
62
    /**
62
    /**
63
     * The constructor is intentionally not public. Use 
63
     * The constructor is intentionally not public. Use 
(-)1436de250f92 (+65 lines)
Added 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.spi.editor.hints;
41
42
import java.util.List;
43
import java.util.Map;
44
import javax.swing.text.Document;
45
46
/**
47
 * Refresher invoked upon mouse click or Alt-Enter. Clients should register
48
 * its implementations inside layer for appropriate mimetype and provide all
49
 * {@link ErrorDescription}s for given line (specified by position).
50
 *
51
 * Contract is that fixes will be already computed in the time of the retrieval.
52
 *
53
 * @author Max Sauer
54
 * @since 1.8.1
55
 */
56
public interface PositionRefresher {
57
58
    /**
59
     * @param position current caret position inside document
60
     * @param doc current document
61
     * @return map of layer name to {@link ErrorDescription}s for current line
62
     */
63
    public Map<String, List<ErrorDescription>> getErrorDescriptionsAt(Context context, Document doc);
64
65
}

Return to bug 150578