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

(-)a/java.source.queries/build.xml (+5 lines)
Line 0 Link Here
1
<?xml version="1.0" encoding="UTF-8"?>
2
<project basedir="." default="netbeans" name="java.source.queries">
3
    <description>Builds, tests, and runs the project org.netbeans.modules.java.source.queries</description>
4
    <import file="../nbbuild/templates/projectized.xml"/>
5
</project>
(-)a/java.source.queries/manifest.mf (+5 lines)
Line 0 Link Here
1
Manifest-Version: 1.0
2
OpenIDE-Module: org.netbeans.modules.java.source.queries
3
OpenIDE-Module-Localizing-Bundle: org/netbeans/modules/java/source/queries/Bundle.properties
4
OpenIDE-Module-Specification-Version: 1.0
5
(-)a/java.source.queries/nbproject/project.properties (+3 lines)
Line 0 Link Here
1
is.autoload=true
2
javac.source=1.6
3
javac.compilerargs=-Xlint -Xlint:-serial
(-)a/java.source.queries/nbproject/project.xml (+64 lines)
Line 0 Link Here
1
<?xml version="1.0" encoding="UTF-8"?>
2
<project xmlns="http://www.netbeans.org/ns/project/1">
3
    <type>org.netbeans.modules.apisupport.project</type>
4
    <configuration>
5
        <data xmlns="http://www.netbeans.org/ns/nb-module-project/3">
6
            <code-name-base>org.netbeans.modules.java.source.queries</code-name-base>
7
            <module-dependencies>
8
                <dependency>
9
                    <code-name-base>org.netbeans.api.annotations.common</code-name-base>
10
                    <build-prerequisite/>
11
                    <compile-dependency/>
12
                    <run-dependency>
13
                        <release-version>1</release-version>
14
                        <specification-version>1.10</specification-version>
15
                    </run-dependency>
16
                </dependency>
17
                <dependency>
18
                    <code-name-base>org.openide.filesystems</code-name-base>
19
                    <build-prerequisite/>
20
                    <compile-dependency/>
21
                    <run-dependency>
22
                        <specification-version>7.48</specification-version>
23
                    </run-dependency>
24
                </dependency>
25
                <dependency>
26
                    <code-name-base>org.openide.util</code-name-base>
27
                    <build-prerequisite/>
28
                    <compile-dependency/>
29
                    <run-dependency>
30
                        <specification-version>8.16</specification-version>
31
                    </run-dependency>
32
                </dependency>
33
                <dependency>
34
                    <code-name-base>org.openide.util.lookup</code-name-base>
35
                    <build-prerequisite/>
36
                    <compile-dependency/>
37
                    <run-dependency>
38
                        <specification-version>8.9</specification-version>
39
                    </run-dependency>
40
                </dependency>
41
            </module-dependencies>
42
            <test-dependencies>
43
                <test-type>
44
                    <name>unit</name>
45
                    <test-dependency>
46
                        <code-name-base>org.netbeans.libs.junit4</code-name-base>
47
                        <compile-dependency/>
48
                    </test-dependency>
49
                    <test-dependency>
50
                        <code-name-base>org.netbeans.modules.nbjunit</code-name-base>
51
                        <recursive/>
52
                        <compile-dependency/>
53
                    </test-dependency>
54
                </test-type>
55
            </test-dependencies>
56
            <friend-packages>
57
                <friend>org.netbeans.modules.form</friend>
58
                <friend>org.netbeans.modules.java.source.queriesimpl</friend>
59
                <package>org.netbeans.modules.java.source.queries.api</package>
60
                <package>org.netbeans.modules.java.source.queries.spi</package>
61
            </friend-packages>
62
        </data>
63
    </configuration>
64
</project>
(-)a/java.source.queries/src/org/netbeans/modules/java/source/queries/APIAccessor.java (+77 lines)
Line 0 Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2011 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
 *
40
 * Portions Copyrighted 2011 Sun Microsystems, Inc.
41
 */
42
package org.netbeans.modules.java.source.queries;
43
44
import org.netbeans.api.annotations.common.NonNull;
45
import org.netbeans.modules.java.source.queries.api.Queries;
46
import org.netbeans.modules.java.source.queries.spi.ModelOperations;
47
import org.openide.util.Exceptions;
48
49
/**
50
 *
51
 * @author Tomas Zezula
52
 */
53
public abstract class APIAccessor {
54
    private static volatile APIAccessor instance;
55
56
    public static void setInstance(@NonNull final APIAccessor _instance) {
57
        assert _instance != null;
58
        instance = _instance;
59
    }
60
61
    public static synchronized APIAccessor getInstance() {
62
        if (instance == null) {
63
            try {
64
                Class.forName(
65
                        Queries.class.getName(),
66
                        true,
67
                        APIAccessor.class.getClassLoader());
68
            } catch (ClassNotFoundException e) {
69
                Exceptions.printStackTrace(e);
70
            }
71
        }
72
        return instance;
73
    }
74
75
    public abstract void attach(@NonNull Queries q, @NonNull ModelOperations ops);
76
    public abstract void detach(@NonNull Queries q);
77
}
(-)a/java.source.queries/src/org/netbeans/modules/java/source/queries/Bundle.properties (+1 lines)
Line 0 Link Here
1
OpenIDE-Module-Name=Java Source Queries
(-)a/java.source.queries/src/org/netbeans/modules/java/source/queries/SPIAccessor.java (+83 lines)
Line 0 Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2011 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
 *
40
 * Portions Copyrighted 2011 Sun Microsystems, Inc.
41
 */
42
package org.netbeans.modules.java.source.queries;
43
44
import org.netbeans.api.annotations.common.NonNull;
45
import org.netbeans.modules.java.source.queries.api.Function;
46
import org.netbeans.modules.java.source.queries.api.Queries;
47
import org.netbeans.modules.java.source.queries.spi.QueriesController;
48
import org.openide.util.Exceptions;
49
50
/**
51
 *
52
 * @author Tomas Zezula
53
 */
54
public abstract class SPIAccessor {
55
56
    private static volatile SPIAccessor instance;
57
58
    public static synchronized SPIAccessor getInstance() {
59
        if (instance == null) {
60
            try {
61
                Class.forName(
62
                        QueriesController.Context.class.getName(),
63
                        true,
64
                        SPIAccessor.class.getClassLoader());
65
                assert instance != null;
66
            } catch (ClassNotFoundException e) {
67
                Exceptions.printStackTrace(e);
68
            }
69
        }
70
        return instance;
71
    }
72
73
    public static void setInstance(@NonNull final SPIAccessor _instance) {
74
        assert _instance != null;
75
        instance = _instance;
76
    }
77
78
    public abstract <P extends Queries,R>  QueriesController.Context<P,R> createContext(
79
            final Function<P,R> fnc,
80
            final P param
81
            );
82
83
}
(-)a/java.source.queries/src/org/netbeans/modules/java/source/queries/api/Function.java (+56 lines)
Line 0 Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2011 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
 *
40
 * Portions Copyrighted 2011 Sun Microsystems, Inc.
41
 */
42
package org.netbeans.modules.java.source.queries.api;
43
44
/**
45
 * Query or update function
46
 * todo: Move to some generic module and change to Function@lt;P,R,E extends Exception&gt;
47
 * @author Tomas Zezula
48
 */
49
public interface Function<P,R> {
50
    /**
51
     * Performs the function on given parameter returning a result
52
     * @param param the function parameter
53
     * @return result
54
     */
55
    R apply (P param) throws QueryException;
56
}
(-)a/java.source.queries/src/org/netbeans/modules/java/source/queries/api/Queries.java (+271 lines)
Line 0 Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2011 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
 *
40
 * Portions Copyrighted 2011 Sun Microsystems, Inc.
41
 */
42
package org.netbeans.modules.java.source.queries.api;
43
44
import java.util.Collection;
45
import org.netbeans.api.annotations.common.CheckForNull;
46
import org.netbeans.api.annotations.common.NonNull;
47
import org.netbeans.api.annotations.common.NullAllowed;
48
import org.netbeans.modules.java.source.queries.APIAccessor;
49
import org.netbeans.modules.java.source.queries.SPIAccessor;
50
import org.netbeans.modules.java.source.queries.spi.ModelOperations;
51
import org.netbeans.modules.java.source.queries.spi.QueriesController;
52
import org.openide.filesystems.FileObject;
53
import org.openide.util.Lookup;
54
import org.openide.util.Parameters;
55
56
/**
57
 * Support for queries
58
 * @author Tomas Zezula
59
 */
60
public class Queries {
61
62
    static {
63
        APIAccessor.setInstance(new Accessor());
64
    }
65
66
    static final QueriesController ctl = Lookup.getDefault().lookup(QueriesController.class);
67
    private final FileObject forFile;
68
    ModelOperations impl;
69
70
    Queries(@NonNull final FileObject forFile) {
71
        assert forFile != null;
72
        this.forFile = forFile;
73
    }
74
75
    /**
76
     * Returns a file for which the {@link Queries} was created.
77
     * @return a file
78
     */
79
    @NonNull
80
    public final FileObject getFile() {
81
        return forFile;
82
    }
83
84
    /**
85
     * Returns the fully qualified names of top level classes in the
86
     * compilation unit represented by {@link Queries#getFile()}
87
     * @return a collection of fully qualified names
88
     * @throws QueryException in case of failure
89
     */
90
    @NonNull
91
    public final Collection<? extends String> getTopLevelClasses() throws QueryException {
92
        return impl.getTopLevelClasses(getFile());
93
    }
94
95
    /**
96
     * Checks if a class represented by fully qualified name is a
97
     * Java Bean. (has no param public constructor).
98
     * @param cls the fully qualified name of the class to be checked
99
     * @return true if the class is a Java Bean
100
     * @throws QueryException in case of failure
101
     */
102
    public final boolean isJavaBean(final @NonNull String cls) throws QueryException {
103
        Parameters.notNull("cls", cls);     //NOI18N
104
        return impl.isJavaBean(cls);
105
    }
106
107
    /**
108
     * Checks if a class represented given fully qualified name is
109
     * available on class path.
110
     * @param cls the fully qualified name of the class
111
     * @return true if the class is available
112
     * @throws QueryException in case of failure
113
     */
114
    public final boolean isAvailable(final @NonNull String cls) throws QueryException {
115
        Parameters.notNull("cls", cls);     //NOI18N
116
        return impl.isAvailable(cls);
117
    }
118
119
    /**
120
     * Returns a binary name as specified by JLS §13.1 for given
121
     * fully qualified name
122
     * @param cls the fully qualified name of the class
123
     * @return the binary name or null if cls cannot be resolved
124
     * @throws QueryException in case of failure
125
     */
126
    @CheckForNull
127
    public final String getClassBinaryName(
128
            @NonNull final String cls) throws QueryException {
129
        Parameters.notNull("cls", cls);     //NOI18N
130
        return impl.getClassBinaryName(cls);
131
    }
132
133
    /**
134
     * Returns the fully qualified name of the super class for
135
     * for given class.
136
     * @param cls the class fully qualified name
137
     * @return the fully qualified name of the super class or null
138
     * when the class has no super type, eg j.l.Object, error type
139
     * @throws QueryException in case of failure
140
     */
141
    @CheckForNull
142
    public final String getSuperClass(final @NonNull String cls) throws QueryException {
143
        Parameters.notNull("cls", cls);     //NOI18N
144
        return impl.getSuperClass(cls);
145
    }
146
147
    /**
148
     * Returns the fully qualified names of the implemented interfaces for
149
     * for given class.
150
     * @param cls the class fully qualified name
151
     * @return the fully qualified names of the implemented interfaces
152
     * @throws QueryException in case of failure
153
     */
154
    @NonNull
155
    public final Collection<? extends String> getInterfaces(final @NonNull String cls) throws QueryException {
156
        Parameters.notNull("cls", cls);     //NOI18N
157
        return impl.getInterfaces(cls);
158
    }
159
160
    /**
161
     * Returns names of the methods complying to given types.
162
     * @param cls the fully qualified name of the class to look up methods in
163
     * @param useRawTypes if true the erasure is done before comparison
164
     * @param returnType the return type of the method specified by the name of the
165
     * primitive type or fully qualified name of the declared type (null represents
166
     * any type)
167
     * @param parameterTypes the types of the method parameters specified by
168
     * name of the primitive type or fully qualified name of the declared type
169
     * (null represent any type)
170
     * @return a collection of method names
171
     * @throws QueryException in case of failure
172
     */
173
    @NonNull
174
    public final Collection<? extends String> getMethodNames(
175
            @NonNull final String cls,
176
            boolean useRawTypes,
177
            @NullAllowed final String returnType,
178
            @NullAllowed final String... parameterTypes) throws QueryException {
179
        Parameters.notNull("cls", cls); //NOI18N
180
        return impl.getMethodNames(cls, useRawTypes, returnType, parameterTypes);
181
    }
182
183
    /**
184
     * Returns names of the fields complying to type.
185
     * @param cls the fully qualified name of the class to look up methods in
186
     * @param useRawTypes if true the erasure is done before comparison
187
     * @param type the type of the field specified by the name of the
188
     * primitive type or fully qualified name of the declared type
189
     * (null represents any type)
190
     * @return a collection of field names
191
     * @throws QueryException in case of failure
192
     */
193
    @NonNull
194
    public final Collection<? extends String> getFieldNames(
195
            @NonNull final String cls,
196
            final boolean useRawTypes,
197
            @NullAllowed final String type) throws QueryException {
198
        Parameters.notNull("cls", cls); //NOI18N
199
        return impl.getFieldNames(cls, useRawTypes, type);
200
    }
201
202
    /**
203
     * Returns annotations annotating given method.
204
     * @param cls the fully qualified name of the class to look up methods in
205
     * @param methodName name of the method
206
     * @param useRawTypes if true the erasure is done before comparison
207
     * @param returnType the return type of the method specified by the name of the
208
     * primitive type or fully qualified name of the declared type
209
     * @param parameterTypes the types of the method parameters specified by
210
     * name of the primitive type or fully qualified name of the declared type
211
     * @return collection of fully qualified names
212
     * @throws QueryException in case of failure
213
     */
214
    @NonNull
215
    public final Collection<? extends String> getMethodAnnotations(
216
            @NonNull final String cls,
217
            @NonNull final String methodName,
218
            final boolean useRawTypes,
219
            @NonNull final String returnType,
220
            @NonNull final String... parameterTypes) throws QueryException {
221
        Parameters.notNull("cls", cls); //NOI18N
222
        Parameters.notNull("methodName", methodName); //NOI18N
223
        Parameters.notNull("returnType", returnType);     //NOI18N
224
        Parameters.notNull("parameterTypes", parameterTypes); //NOI18N
225
        return impl.getMethodAnnotations(cls, methodName, useRawTypes, returnType, parameterTypes);
226
    }
227
228
    /**
229
     * Performs the query
230
     * @param forFile file implying the scope to perform query on
231
     * @param queryFnc the query function
232
     * @return the result of query function
233
     * @throws QueryException in case of exception
234
     */
235
    @CheckForNull
236
    public static <T> T query (
237
        @NonNull final FileObject forFile,
238
        @NonNull final Function<Queries,T> queryFnc) throws QueryException {
239
        Parameters.notNull("forFile", forFile);     //NOI18N
240
        Parameters.notNull("queryFnc", queryFnc);   //NOI18N
241
        if (ctl == null) {
242
            throw new IllegalStateException("No QueriesController found in the Lookup");    //NOI18N
243
        }
244
        final Queries q = new Queries(forFile);
245
        final QueriesController.Context<Queries,T> ctx = SPIAccessor.getInstance().createContext(queryFnc, q);
246
        return ctl.runQuery(ctx);
247
    }
248
249
250
    private void attach(@NonNull final ModelOperations impl) {
251
        assert impl != null;
252
        this.impl = impl;
253
    }
254
255
    private void detach() {
256
        this.impl = null;
257
    }
258
259
    private static class Accessor extends APIAccessor {
260
261
        @Override
262
        public void attach(Queries q, ModelOperations ops) {
263
            q.attach(ops);
264
        }
265
266
        @Override
267
        public void detach(Queries q) {
268
            q.detach();
269
        }
270
    }
271
}
(-)a/java.source.queries/src/org/netbeans/modules/java/source/queries/api/QueryException.java (+64 lines)
Line 0 Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2011 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
 *
40
 * Portions Copyrighted 2011 Sun Microsystems, Inc.
41
 */
42
package org.netbeans.modules.java.source.queries.api;
43
44
/**
45
 * Exception thrown by queries
46
 * @author Tomas Zezula
47
 */
48
public class QueryException extends Exception {
49
50
    public QueryException() {
51
    }
52
53
    public QueryException(final String message) {
54
        super(message);
55
    }
56
57
    public QueryException(final Throwable rootCause) {
58
        super(rootCause);
59
    }
60
61
    public QueryException(final String message, final Throwable rootCause) {
62
        super (message, rootCause);
63
    }
64
}
(-)a/java.source.queries/src/org/netbeans/modules/java/source/queries/api/Updates.java (+182 lines)
Line 0 Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2011 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
 *
40
 * Portions Copyrighted 2011 Sun Microsystems, Inc.
41
 */
42
package org.netbeans.modules.java.source.queries.api;
43
44
import java.util.Collection;
45
import org.netbeans.api.annotations.common.NonNull;
46
import org.netbeans.modules.java.source.queries.SPIAccessor;
47
import org.netbeans.modules.java.source.queries.spi.QueriesController;
48
import org.openide.filesystems.FileObject;
49
import org.openide.util.Parameters;
50
51
/**
52
 * Support for modifications
53
 * @author Tomas Zezula
54
 */
55
public final class Updates extends Queries {
56
57
    Updates(@NonNull final FileObject forFile) {
58
        super(forFile);
59
    }
60
61
    /**
62
     * Modifies class interfaces.
63
     * @param cls the fully qualified name of class to be changed
64
     * @param toAdd the {@link Collection} of fully qualified names of
65
     * interfaces to be added
66
     * @param toRemove the {@link Collection} of fully qualified names of
67
     * interfaces to be removed
68
     * @throws QueryException in case of failure
69
     */
70
    public void modifyInterfaces(
71
            @NonNull String cls,
72
            @NonNull Collection<? extends String> toAdd,
73
            @NonNull Collection<? extends String> toRemove) throws QueryException {
74
        Parameters.notNull("cls", cls);     //NOI18N
75
        Parameters.notNull("toAdd", toAdd);     //NOI18N
76
        Parameters.notNull("toRemove", toRemove);     //NOI18N
77
        impl.modifyInterfaces(cls,toAdd,toRemove);
78
    }
79
80
    /**
81
     * Modifies method annotations.
82
     * @param cls the fully qualified name of the class to look up methods in
83
     * @param methodName name of the method
84
     * @param useRawTypes if true the erasure is done before comparison
85
     * @param returnType the return type of the method specified by the name of the
86
     * primitive type or fully qualified name of the declared type
87
     * @param parameterTypes the types of the method parameters specified by
88
     * name of the primitive type or fully qualified name of the declared type
89
     * @param toAdd the {@link Collection} of fully qualified names of
90
     * annotations to be added
91
     * @param toRemove the {@link Collection} of fully qualified names of
92
     * annotations to be removed
93
     * @throws QueryException in case of failure
94
     */
95
    public void modifyMethodAnnotations(
96
            @NonNull final String cls,
97
            @NonNull final String methodName,
98
            final boolean useRawTypes,
99
            @NonNull final String returnType,
100
            @NonNull final String[] parameterTypes,
101
            @NonNull final Collection<? extends String> toAdd,
102
            @NonNull final Collection<? extends String> toRemove) throws QueryException {
103
        Parameters.notNull("cls", cls); //NOI18N
104
        Parameters.notNull("methodName", methodName); //NOI18N
105
        Parameters.notNull("returnType", returnType);     //NOI18N
106
        Parameters.notNull("parameterTypes", parameterTypes); //NOI18N
107
        Parameters.notNull("toAdd", toAdd); //NOI18N
108
        Parameters.notNull("toRemove", toRemove); //NOI18N
109
        impl.modifyMethodAnnotations(
110
                cls,
111
                methodName,
112
                useRawTypes,
113
                returnType,
114
                parameterTypes,
115
                toAdd,
116
                toRemove);
117
    }
118
119
    /**
120
     * Sets class super class.
121
     * @param cls the fully qualified name of class to be changed
122
     * @param superCls the fully qualified name of super class
123
     * @throws QueryException in case of failure
124
     */
125
    public void setSuperClass(
126
            @NonNull String cls,
127
            @NonNull String superCls) throws QueryException {
128
        Parameters.notNull("cls", cls);     //NOI18N
129
        Parameters.notNull("superCls", superCls);   //NOI18N
130
        impl.setSuperClass(cls, superCls);
131
    }
132
133
    /**
134
     * Adds required imports into the java source if needed.
135
     * @param requiredFQNs the fully qualified names of imports to be added
136
     * @throws QueryException in case of failure
137
     */
138
    public void fixImports(
139
            @NonNull final Collection<? extends String> requiredFQNs) throws QueryException {
140
        Parameters.notNull("requiredFQNs", requiredFQNs);     //NOI18N
141
        impl.fixImports(getFile(),requiredFQNs);
142
    }
143
144
    /**
145
     * Renames a field in a class.
146
     * @param cls the fully qualified name of the class owning the field
147
     * @param oldName the old field name
148
     * @param newName the new field name
149
     * @throws QueryException in case of failure
150
     */
151
    public void renameField(
152
            @NonNull final String cls,
153
            @NonNull final String oldName,
154
            @NonNull final String newName) throws QueryException {
155
        Parameters.notNull("oldName", oldName);     //NOI18N
156
        Parameters.notNull("newName", newName);     //NOI18N
157
        impl.renameField(cls,oldName,newName);
158
    }
159
160
161
    /**
162
     * Performs the update.
163
     * @param forFile file implying the scope to perform query on
164
     * @param updateFnc  the query function. If the function returns true
165
     * the changes are applied otherwise the changes are rolled back.
166
     * @throws QueryException in case of exception
167
     */
168
    public static void update(
169
            @NonNull final FileObject forFile,
170
            @NonNull final Function<Updates,Boolean> updateFnc) throws QueryException {
171
        Parameters.notNull("forFile", forFile);     //NOI18N
172
        Parameters.notNull("updateFnc", forFile);   //NOI18N
173
        if (ctl == null) {
174
            throw new IllegalStateException("No QueriesController found in the Lookup");    //NOI18N
175
        }
176
        final Updates u = new Updates(forFile);
177
        final QueriesController.Context<Updates,Boolean> ctx =
178
                SPIAccessor.getInstance().createContext(updateFnc, u);
179
        ctl.runUpdate(ctx);
180
    }
181
182
}
(-)a/java.source.queries/src/org/netbeans/modules/java/source/queries/spi/ModelOperations.java (+250 lines)
Line 0 Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2011 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
 *
40
 * Portions Copyrighted 2011 Sun Microsystems, Inc.
41
 */
42
package org.netbeans.modules.java.source.queries.spi;
43
44
import java.util.Collection;
45
import org.netbeans.api.annotations.common.CheckForNull;
46
import org.netbeans.api.annotations.common.NonNull;
47
import org.netbeans.api.annotations.common.NullAllowed;
48
import org.netbeans.modules.java.source.queries.api.QueryException;
49
import org.netbeans.modules.java.source.queries.api.Queries;
50
import org.netbeans.modules.java.source.queries.api.Updates;
51
import org.openide.filesystems.FileObject;
52
53
/**
54
 * SPI for {@link Queries} and {@link Updates}.
55
 * The instance is created by implementor of {@link QueriesController}
56
 * and passed to {@link QueriesController.Context}
57
 * @author Tomas Zezula
58
 */
59
public interface ModelOperations {
60
61
    /**
62
     * Returns the fully qualified names of top level classes in the
63
     * compilation unit represented by given file
64
     * @param file to get the top level classes
65
     * @return a collection of fully qualified names
66
     * @throws QueryException in case of failure
67
     */
68
    @NonNull
69
    Collection<? extends String> getTopLevelClasses(@NonNull FileObject file) throws QueryException;
70
71
    /**
72
     * Checks if a class represented by fully qualified name is a
73
     * Java Bean (has no param public constructor).
74
     * @param cls the fully qualified name of the class to be checked
75
     * @return true if the class is a Java Bean
76
     * @throws QueryException in case of failure
77
     */
78
    boolean isJavaBean(@NonNull String cls) throws QueryException;
79
80
    /**
81
     * Checks if a class represented given fully qualified name is
82
     * available on class path.
83
     * @param cls the fully qualified name of the class
84
     * @return true if the class is available
85
     * @throws QueryException in case of failure
86
     */
87
    boolean isAvailable(@NonNull String cls) throws QueryException;
88
89
    /**
90
     * Returns the fully qualified name of the super class for
91
     * for given class.
92
     * @param cls the class fully qualified name
93
     * @return the fully qualified name of the super class or null
94
     * when the class has no super type, eg j.l.Object, error type
95
     * @throws QueryException in case of failure
96
     */
97
    @CheckForNull
98
    String getSuperClass(@NonNull String cls) throws QueryException;
99
100
    /**
101
     * Returns the fully qualified names of the implemented interfaces for
102
     * for given class.
103
     * @param cls the class fully qualified name
104
     * @return the fully qualified names of the implemented interfaces
105
     * @throws QueryException in case of failure
106
     */
107
    @NonNull
108
    public Collection<? extends String> getInterfaces(@NonNull String cls) throws QueryException;
109
110
    /**
111
     * Returns names of the methods complying to given types.
112
     * @param cls the fully qualified name of the class to look up methods in
113
     * @param useRawTypes if true the erasure is done before comparison
114
     * @param returnType the return type of the method specified by the name of the
115
     * primitive type or fully qualified name of the declared type (null represents
116
     * any type)
117
     * @param parameterTypes the types of the method parameters specified by
118
     * name of the primitive type or fully qualified name of the declared type
119
     * (null represent any type)
120
     * @return a collection of method names
121
     * @throws QueryException in case of failure
122
     */
123
    @NonNull
124
    Collection<? extends String> getMethodNames(
125
            @NonNull String cls,
126
            boolean useRawTypes,
127
            @NullAllowed String returnType,
128
            @NullAllowed String... parameterTypes) throws QueryException;
129
130
131
    /**
132
     * Returns names of the fields complying to type.
133
     * @param cls the fully qualified name of the class to look up methods in
134
     * @param useRawTypes if true the erasure is done before comparison
135
     * @param type the type of the field specified by the name of the
136
     * primitive type or fully qualified name of the declared type
137
     * (null represents any type)
138
     * @return a collection of field names
139
     * @throws QueryException in case of failure
140
     */
141
    @NonNull
142
    Collection<? extends String> getFieldNames(
143
            @NonNull String cls,
144
            boolean useRawTypes,
145
            @NullAllowed String type) throws QueryException;
146
147
148
    /**
149
     * Returns annotations annotating given method.
150
     * @param cls the fully qualified name of the class to look up methods in
151
     * @param methodName name of the method
152
     * @param useRawTypes if true the erasure is done before comparison
153
     * @param returnType the return type of the method specified by the name of the
154
     * primitive type or fully qualified name of the declared type
155
     * @param parameterTypes the types of the method parameters specified by
156
     * name of the primitive type or fully qualified name of the declared type
157
     * @return collection of fully qualified names
158
     * @throws QueryException in case of failure
159
     */
160
    Collection<? extends String> getMethodAnnotations(
161
            @NonNull String cls,
162
            @NonNull String methodName,
163
            boolean useRawTypes,
164
            @NonNull String returnType,
165
            @NonNull String... parameterTypes) throws QueryException;
166
167
    /**
168
     * Returns a binary name as specified by JLS §13.1 for given
169
     * fully qualified name.
170
     * @param cls the fully qualified name of the class
171
     * @return the binary name or null if cls cannot be resolved
172
     * @throws QueryException in case of failure
173
     */
174
    @CheckForNull
175
    String getClassBinaryName(@NonNull String cls) throws QueryException;
176
177
178
    /**
179
     * Adds required imports into the java source if needed.
180
     * @param file a file to add imports into
181
     * @param requiredFQNs the fully qualified names of imports to be added
182
     * @throws QueryException in case of failure
183
     */
184
    void fixImports(
185
            @NonNull FileObject file,
186
            Collection<? extends String> requiredFQNs) throws QueryException;
187
188
189
    /**
190
     * Modifies class interfaces.
191
     * @param cls the fully qualified name of class to be changed
192
     * @param toAdd the {@link Collection} of fully qualified names of
193
     * interfaces to be added
194
     * @param toRemove the {@link Collection} of fully qualified names of
195
     * interfaces to be removed
196
     * @throws QueryException in case of failure
197
     */
198
    void modifyInterfaces(
199
            @NonNull String cls,
200
            @NonNull Collection<? extends String> toAdd,
201
            @NonNull Collection<? extends String> toRemove) throws QueryException;
202
203
204
    /**
205
     * Modifies method annotations.
206
     * @param cls the fully qualified name of the class to look up methods in
207
     * @param methodName name of the method
208
     * @param useRawTypes if true the erasure is done before comparison
209
     * @param returnType the return type of the method specified by the name of the
210
     * primitive type or fully qualified name of the declared type
211
     * @param parameterTypes the types of the method parameters specified by
212
     * name of the primitive type or fully qualified name of the declared type
213
     * @param toAdd the {@link Collection} of fully qualified names of
214
     * annotations to be added
215
     * @param toRemove the {@link Collection} of fully qualified names of
216
     * annotations to be removed
217
     * @throws QueryException in case of failure
218
     */
219
    void modifyMethodAnnotations(
220
            @NonNull String cls,
221
            @NonNull String methodName,
222
            boolean useRawTypes,
223
            @NonNull String returnType,
224
            @NonNull String[] parameterTypes,
225
            @NonNull Collection<? extends String> toAdd,
226
            @NonNull Collection<? extends String> toRemove) throws QueryException;
227
228
    /**
229
     * Sets class super class.
230
     * @param cls the fully qualified name of class to be changed
231
     * @param superCls the fully qualified name of super class
232
     * @throws QueryException in case of failure
233
     */
234
    void setSuperClass(
235
            @NonNull String cls,
236
            @NonNull String superCls) throws QueryException;
237
238
239
    /**
240
     * Renames a field in a class.
241
     * @param cls the fully qualified name of the class owning the field
242
     * @param oldName the old field name
243
     * @param newName the new field name
244
     * @throws QueryException in case of failure
245
     */
246
    void renameField(
247
            @NonNull String cls,
248
            @NonNull String oldName,
249
            @NonNull String newName) throws QueryException;
250
}
(-)a/java.source.queries/src/org/netbeans/modules/java/source/queries/spi/QueriesController.java (+135 lines)
Line 0 Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2011 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
 *
40
 * Portions Copyrighted 2011 Sun Microsystems, Inc.
41
 */
42
package org.netbeans.modules.java.source.queries.spi;
43
44
import org.netbeans.api.annotations.common.NonNull;
45
import org.netbeans.modules.java.source.queries.APIAccessor;
46
import org.netbeans.modules.java.source.queries.api.QueryException;
47
import org.netbeans.modules.java.source.queries.SPIAccessor;
48
import org.netbeans.modules.java.source.queries.api.Function;
49
import org.netbeans.modules.java.source.queries.api.Queries;
50
import org.netbeans.modules.java.source.queries.api.Updates;
51
import org.openide.filesystems.FileObject;
52
53
/**
54
 * SPI for the {@link Queries} and {@link Updates}.
55
 * The implementation is registered in META-INF/services.
56
 * @author Tomas Zezula
57
 */
58
public interface QueriesController {
59
    /**
60
     * Performs the query.
61
     * @param ctx the query {@link Context} holding the
62
     * query function and query parameter
63
     * @return the result of the query function
64
     * @throws IOException in case of error
65
     */
66
    <R> R runQuery(@NonNull Context<Queries,R> ctx) throws QueryException;
67
68
    /**
69
     * Performs the modification.
70
     * @param ctx the modification {@link Context} holding the
71
     * modification function and modification parameter
72
     * @throws IOException in case of error
73
     */
74
    void runUpdate(@NonNull Context<Updates,Boolean> ctx) throws QueryException;
75
76
    /**
77
     * Context of the query or modification
78
     */
79
    public static final class Context<P extends Queries,R> {
80
81
        static {
82
            SPIAccessor.setInstance(new Accessor());
83
        }
84
85
        private final Function<P,R> toRun;
86
        private final P param;
87
        private final FileObject forFile;
88
89
        Context (
90
            @NonNull final FileObject forFile,
91
            @NonNull final Function<P,R> toRun,
92
            @NonNull final P param) {
93
            assert forFile != null;
94
            assert toRun != null;
95
            assert param != null;
96
            this.toRun = toRun;
97
            this.param = param;
98
            this.forFile = forFile;
99
        }
100
101
        /**
102
         * Return the file for which the {@link Queries} or
103
         * {@link Updates} instance was created.
104
         * @return the file
105
         */
106
        public FileObject getFile(){
107
            return forFile;
108
        }
109
110
        /**
111
         * Performs the query function on query parameter.
112
         * using the provided {@link ModelOperations}
113
         * @param op the {@link ModelOperations} SPI to used to
114
         * perform the operation.
115
         * @return the query function result
116
         */
117
        public R execute(ModelOperations op) throws QueryException {
118
            APIAccessor.getInstance().attach(param, op);
119
            try {
120
                return toRun.apply(param);
121
            } finally {
122
                APIAccessor.getInstance().detach(param);
123
            }
124
        }
125
126
        private static class Accessor extends SPIAccessor {
127
            @Override
128
            public <P extends Queries,R>  QueriesController.Context<P,R> createContext(
129
                final Function<P,R> fnc,
130
                final P param) {
131
                return new Context<P, R>(param.getFile(), fnc, param);
132
            }
133
        }
134
    }
135
}
(-)a/java.source.queries/test/unit/src/org/netbeans/modules/java/source/queries/spi/ModelOperationsTest.java (+760 lines)
Line 0 Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2011 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
 *
40
 * Portions Copyrighted 2011 Sun Microsystems, Inc.
41
 */
42
package org.netbeans.modules.java.source.queries.spi;
43
import java.io.File;
44
import java.io.IOException;
45
import java.io.OutputStreamWriter;
46
import java.io.PrintWriter;
47
import java.util.Arrays;
48
import java.util.Collection;
49
import java.util.Collections;
50
import java.util.HashSet;
51
import java.util.List;
52
import java.util.Set;
53
import org.netbeans.api.annotations.common.NonNull;
54
import org.netbeans.api.annotations.common.NullAllowed;
55
import org.netbeans.junit.NbTestCase;
56
import org.netbeans.modules.java.source.queries.api.Function;
57
import org.netbeans.modules.java.source.queries.api.Queries;
58
import org.netbeans.modules.java.source.queries.api.QueryException;
59
import org.netbeans.modules.java.source.queries.api.Updates;
60
import org.openide.filesystems.FileLock;
61
import org.openide.filesystems.FileObject;
62
import org.openide.filesystems.FileUtil;
63
import org.openide.util.Lookup;
64
65
/**
66
 *
67
 * @author Tomas Zezula
68
 */
69
public class ModelOperationsTest extends NbTestCase {
70
71
    protected static final String[] TEST_1 = {
72
        "org.me.test",
73
        "Test1",
74
        "package org.me.test;\n"+
75
        "import java.util.Map;\n"+
76
        "public class Test1{\n"+
77
        "    int a, b;\n"+
78
        "    float c\n;"+
79
        "    Test1 d\n;"+
80
        "    java.util.List e;\n"+
81
        "    Map<String,String> f;\n"+
82
        "}"
83
    };
84
85
    protected static final String[] TEST_2 = {
86
        "org.me.test",
87
        "Test2",
88
        "package org.me.test;\n"+
89
        "public class Test2 extends Exception implements Runnable {\n"+
90
        "    public Test2(int a){}\n"+
91
        "    public void run(){}\n"+
92
        "}\n"+
93
        "class Test2Other implements Runnable,java.io.Serializable{\n" +
94
        "    public void run(){}\n"+
95
        "}"
96
    };
97
98
    protected static final String[] TEST_3 = {
99
        "org.me.test",
100
        "Test3",
101
        "package org.me.test;\n"+
102
        "public class Test3{\n"+
103
        "    Test3(){}\n"+
104
        "}"
105
    };
106
107
    protected static final String[] TEST_4 = {
108
        "org.me.test",
109
        "Test4",
110
        "package org.me.test;\n"+
111
        "import java.util.Map;\n"+
112
        "public class Test4{\n"+
113
        "    void m1() {}\n"+
114
        "    void m2(int a){}\n"+
115
        "    int m3(int a, int b){}\n"+
116
        "    java.util.List m4(Map<String,String>a, Map<String,String>b){}\n"+
117
        "    java.util.List<String> m5(Map<String,java.util.List<String>>a, String b){}\n"+
118
        "    void m6(int... a){}\n"+
119
        "    int m7(int... a){}\n" +
120
        "}"
121
    };
122
123
    protected static final String[] TEST_5 = {
124
        "org.me.test",
125
        "Test5",
126
        "package org.me.test;\n"+
127
        "import java.util.Map;\n"+
128
        "public class Test5{\n"+
129
        "    void m1() {}\n"+
130
        "    @SuppressWarnings void m1(int a){}\n"+
131
        "    @SuppressWarnings int m2(int a, int b){}\n"+
132
        "}"
133
    };
134
135
    protected static final String[] TEST_6 = {
136
        "org.me.test",
137
        "Test6",
138
        "package org.me.test;\n"+
139
        "public class Test6{\n"+
140
        "    int a;\n"+
141
        "}"
142
    };
143
144
    protected FileObject srcRoot;
145
146
    public ModelOperationsTest(String testName) {
147
        super(testName);
148
    }
149
150
    @Override
151
    protected void setUp() throws Exception {
152
        this.clearWorkDir();
153
        srcRoot = FileUtil.createFolder(new File (getWorkDir(),"src"));
154
    }
155
156
    public void testGetTopLevelClasses() throws Exception {
157
        doTestGetTopLevelClasses(TEST_1, Arrays.asList("org.me.test.Test1"));
158
        doTestGetTopLevelClasses(TEST_2, Arrays.asList("org.me.test.Test2","org.me.test.Test2Other"));
159
    }
160
161
    private void doTestGetTopLevelClasses(
162
            @NonNull final String[] testCase,
163
            @NonNull final Collection<? extends String> expected) throws Exception {
164
        final FileObject fo1 = prepareTest(
165
            srcRoot,
166
            testCase[0],
167
            testCase[1],
168
            testCase[2]);
169
        final Collection<? extends String> tlc = Queries.query(
170
            fo1,
171
            new Function<Queries, Collection<? extends String>>(){
172
                @Override
173
                public Collection<? extends String> apply(Queries param) throws QueryException {
174
                    return param.getTopLevelClasses();
175
                }
176
            });
177
        assertContentEquals(expected,tlc);
178
    }
179
180
    public void testIsJavaBean() throws Exception {
181
        doTestIsJavaBean(TEST_1, "org.me.test.Test1", true);
182
        doTestIsJavaBean(TEST_2, "org.me.test.Test2", false);
183
        doTestIsJavaBean(TEST_2, "org.me.test.Test2Other", false);
184
        doTestIsJavaBean(TEST_3, "org.me.test.Test3", false);
185
    }
186
187
    private void doTestIsJavaBean(
188
            @NonNull final String[] testCase,
189
            @NonNull final String fqn,
190
            final boolean expected) throws Exception {
191
        final FileObject file = prepareTest(
192
            srcRoot,
193
            testCase[0],
194
            testCase[1],
195
            testCase[2]);
196
        final Boolean res = Queries.query(
197
            file,
198
            new Function<Queries, Boolean>(){
199
                @Override
200
                public Boolean apply(Queries param) throws QueryException {
201
                    return param.isJavaBean(fqn);
202
                }
203
            });
204
        assertEquals(expected, res.booleanValue());
205
    }
206
207
    public void testIsAvialable() throws Exception {
208
        doTestIsAvailable(TEST_1, "org.me.test.Test1", true);
209
        doTestIsAvailable(TEST_1, "java.lang.String", true);
210
    }
211
212
    private void doTestIsAvailable(
213
            @NonNull final String[] testCase,
214
            @NonNull final String fqn,
215
            final boolean expected) throws Exception {
216
        final FileObject file = prepareTest(
217
            srcRoot,
218
            testCase[0],
219
            testCase[1],
220
            testCase[2]);
221
        final Boolean res = Queries.query(
222
            file,
223
            new Function<Queries, Boolean>(){
224
                @Override
225
                public Boolean apply(Queries param) throws QueryException {
226
                    return param.isAvailable(fqn);
227
                }
228
            });
229
        assertEquals(expected, res.booleanValue());
230
    }
231
232
    public void testGetSuperClass() throws Exception {
233
        doTestGetSuperClass(TEST_1, "org.me.test.Test1", "java.lang.Object");
234
        doTestGetSuperClass(TEST_2, "org.me.test.Test2", "java.lang.Exception");
235
        doTestGetSuperClass(TEST_3, "java.lang.RuntimeException", "java.lang.Exception");
236
        doTestGetSuperClass(TEST_3, "java.lang.Object", null);
237
    }
238
239
    private void doTestGetSuperClass(
240
            @NonNull final String[] testCase,
241
            @NonNull final String fqn,
242
            @NonNull final String expected) throws Exception {
243
        final FileObject file = prepareTest(
244
            srcRoot,
245
            testCase[0],
246
            testCase[1],
247
            testCase[2]);
248
        final String res = Queries.query(
249
            file,
250
            new Function<Queries, String>(){
251
                @Override
252
                public String apply(Queries param) throws QueryException {
253
                    return param.getSuperClass(fqn);
254
                }
255
            });
256
        assertEquals(expected, res);
257
    }
258
259
    public void testGetInterfaces() throws Exception {
260
        doTestGetInterfaces(TEST_1, "org.me.test.Test1", Collections.<String>emptyList());
261
        doTestGetInterfaces(TEST_2, "org.me.test.Test2", Collections.singleton("java.lang.Runnable"));
262
        doTestGetInterfaces(TEST_2, "org.me.test.Test2Other",
263
            Arrays.asList("java.lang.Runnable","java.io.Serializable"));
264
    }
265
266
    private void doTestGetInterfaces(
267
            @NonNull final String[] testCase,
268
            @NonNull final String fqn,
269
            @NonNull final Collection< ? extends String> expected) throws Exception {
270
        final FileObject file = prepareTest(
271
            srcRoot,
272
            testCase[0],
273
            testCase[1],
274
            testCase[2]);
275
        final Collection< ? extends String> res = Queries.query(
276
            file,
277
            new Function<Queries, Collection<? extends String>>(){
278
                @Override
279
                public Collection<? extends String> apply(Queries param) throws QueryException {
280
                    return param.getInterfaces(fqn);
281
                }
282
            });
283
        assertContentEquals(expected, res);
284
    }
285
286
    public void testGetBinaryName() throws Exception {
287
        doTestGetBinaryName(TEST_1,"org.me.test.Test1","org.me.test.Test1");
288
        doTestGetBinaryName(TEST_2,"org.me.test.Test2Other","org.me.test.Test2Other");
289
        doTestGetBinaryName(TEST_2,"java.util.Map","java.util.Map");
290
        doTestGetBinaryName(TEST_2,"java.util.Map.Entry","java.util.Map$Entry");
291
    }
292
293
    private void doTestGetBinaryName(
294
            @NonNull final String[] testCase,
295
            @NonNull final String fqn,
296
            @NonNull final String expected) throws Exception {
297
        final FileObject file = prepareTest(
298
            srcRoot,
299
            testCase[0],
300
            testCase[1],
301
            testCase[2]);
302
        final String res = Queries.query(
303
            file,
304
            new Function<Queries, String>(){
305
                @Override
306
                public String apply(Queries param) throws QueryException {
307
                    return param.getClassBinaryName(fqn);
308
                }
309
            });
310
        assertEquals(expected, res);
311
    }
312
313
    public void testGetFieldNames() throws Exception {
314
        doTestGetFieldNames(TEST_1,"org.me.test.Test1", false, "org.me.test.Test1", Collections.singletonList("d"));
315
        doTestGetFieldNames(TEST_1,"org.me.test.Test1", false, "float", Collections.singletonList("c"));
316
        doTestGetFieldNames(TEST_1,"org.me.test.Test1", false, "int", Arrays.asList("a","b"));
317
        doTestGetFieldNames(TEST_1,"org.me.test.Test1", false, "java.util.List", Collections.singletonList("e"));
318
        doTestGetFieldNames(TEST_1,"org.me.test.Test1", true, "java.util.List", Collections.singletonList("e"));
319
        doTestGetFieldNames(TEST_1,"org.me.test.Test1", false, "java.util.List<java.lang.String>", Collections.<String>emptyList());
320
        doTestGetFieldNames(TEST_1,"org.me.test.Test1", true, "java.util.List<java.lang.String>", Collections.singletonList("e"));
321
        doTestGetFieldNames(TEST_1,"org.me.test.Test1", false, "java.util.Map", Collections.<String>emptyList());
322
        doTestGetFieldNames(TEST_1,"org.me.test.Test1", true, "java.util.Map", Collections.singletonList("f"));
323
        doTestGetFieldNames(TEST_1,"org.me.test.Test1", false, "java.util.Map<java.lang.String,java.lang.String>", Collections.singletonList("f"));
324
        doTestGetFieldNames(TEST_1,"org.me.test.Test1", false, null, Arrays.asList("a","b","c","d","e","f"));
325
    }
326
327
    private void doTestGetFieldNames(
328
            @NonNull final String[] testCase,
329
            @NonNull final String fqn,
330
            final boolean useRT,
331
            @NonNull final String type,
332
            @NonNull final Collection<? extends String> expected) throws Exception {
333
        final FileObject file = prepareTest(
334
            srcRoot,
335
            testCase[0],
336
            testCase[1],
337
            testCase[2]);
338
        final Collection<? extends String> res = Queries.query(
339
            file,
340
            new Function<Queries, Collection<? extends String>>(){
341
                @Override
342
                public Collection< ? extends String> apply(Queries param) throws QueryException {
343
                    return param.getFieldNames(fqn, useRT, type);
344
                }
345
            });
346
        assertContentEquals(expected, res);
347
    }
348
349
    public void testGetMethodNames() throws Exception {
350
        doTestGetMethodNames(TEST_4,"org.me.test.Test4", false,
351
                "void",
352
                Collections.<String>emptyList(),
353
                Collections.singletonList("m1"));
354
        doTestGetMethodNames(TEST_4,"org.me.test.Test4", false,
355
                "void",
356
                Collections.<String>singletonList("int"),
357
                Collections.singletonList("m2"));
358
        doTestGetMethodNames(TEST_4,"org.me.test.Test4", false,
359
                "int",
360
                Arrays.asList(new String[]{"int","int"}),
361
                Collections.singletonList("m3"));
362
        doTestGetMethodNames(TEST_4,"org.me.test.Test4", true,
363
                "java.util.List",
364
                Arrays.asList("java.util.Map","java.util.Map"),
365
                Collections.singletonList("m4"));
366
        doTestGetMethodNames(TEST_4,"org.me.test.Test4", false,
367
                "java.util.List",
368
                Arrays.asList("java.util.Map","java.util.Map"),
369
                Collections.<String>emptyList());
370
        doTestGetMethodNames(TEST_4,"org.me.test.Test4", false,
371
                "java.util.List<java.lang.String>",
372
                Arrays.asList("java.util.Map<java.lang.String,java.lang.String>","java.util.Map<java.lang.String,java.lang.String>"),
373
                Collections.<String>emptyList());
374
        doTestGetMethodNames(TEST_4,"org.me.test.Test4", false,
375
                "java.util.List",
376
                Arrays.asList("java.util.Map<java.lang.String,java.lang.String>","java.util.Map<java.lang.String,java.lang.String>"),
377
                Collections.singletonList("m4"));
378
        doTestGetMethodNames(TEST_4,"org.me.test.Test4", true,
379
                "java.util.List",
380
                Arrays.asList("java.util.Map","java.lang.String"),
381
                Collections.singletonList("m5"));
382
        doTestGetMethodNames(TEST_4,"org.me.test.Test4", false,
383
                "java.util.List",
384
                Arrays.asList("java.util.Map","java.lang.String"),
385
                Collections.<String>emptyList());
386
        doTestGetMethodNames(TEST_4,"org.me.test.Test4", false,
387
                "java.util.List",
388
                Arrays.asList("java.util.Map<java.lang.String,java.util.List<java.lang.String>>","java.lang.String"),
389
                Collections.<String>emptyList());
390
        doTestGetMethodNames(TEST_4,"org.me.test.Test4", false,
391
                "java.util.List<java.lang.String>",
392
                Arrays.asList("java.util.Map","java.lang.String"),
393
                Collections.<String>emptyList());
394
        doTestGetMethodNames(TEST_4,"org.me.test.Test4", false,
395
                "java.util.List<java.lang.String>",
396
                Arrays.asList("java.util.Map<java.lang.String,java.util.List<java.lang.String>>","java.lang.String"),
397
                Collections.singletonList("m5"));
398
        doTestGetMethodNames(TEST_4,"org.me.test.Test4", false,
399
                "void",
400
                Collections.singletonList("int[]"),
401
                Collections.singletonList("m6"));
402
        doTestGetMethodNames(TEST_4,"org.me.test.Test4", false,
403
                null,
404
                Collections.singletonList("int[]"),
405
                Arrays.asList("m6","m7"));
406
                doTestGetMethodNames(TEST_4,"org.me.test.Test4", false,
407
                "void",
408
                null,
409
                Arrays.asList("m1","m2","m6"));
410
        doTestGetMethodNames(TEST_4,"org.me.test.Test4", false,
411
                null,
412
                null,
413
                Arrays.asList("m1","m2","m3","m4","m5","m6","m7"));
414
    }
415
416
    private void doTestGetMethodNames(
417
            @NonNull final String[] testCase,
418
            @NonNull final String fqn,
419
            final boolean useRT,
420
            @NonNull final String retType,
421
            @NonNull final List<? extends String> paramTypes,
422
            @NonNull final Collection<? extends String> expected) throws Exception {
423
        final FileObject file = prepareTest(
424
            srcRoot,
425
            testCase[0],
426
            testCase[1],
427
            testCase[2]);
428
        final Collection<? extends String> res = Queries.query(
429
            file,
430
            new Function<Queries, Collection<? extends String>>(){
431
                @Override
432
                public Collection< ? extends String> apply(Queries param) throws QueryException {
433
                    return param.getMethodNames(
434
                        fqn,
435
                        useRT,
436
                        retType,
437
                        paramTypes == null ? null : paramTypes.toArray(new String[paramTypes.size()]));
438
                }
439
            });
440
        assertContentEquals(expected, res);
441
    }
442
443
    public void testGetMethodAnnotations() throws Exception {
444
        doTestGetMethodAnnotations(TEST_5,"org.me.test.Test5","m1",false,
445
                "void",
446
                Collections.<String>emptyList(),
447
                Collections.<String>emptyList());
448
        doTestGetMethodAnnotations(TEST_5,"org.me.test.Test5", "m1",false,
449
                "void",
450
                Collections.singletonList("int"),
451
                Collections.singletonList("java.lang.SuppressWarnings"));
452
        doTestGetMethodAnnotations(TEST_5,"org.me.test.Test5", "m2",false,
453
                "int",
454
                Arrays.asList("int","int"),
455
                Collections.singletonList("java.lang.SuppressWarnings"));
456
    }
457
458
    private void doTestGetMethodAnnotations(
459
            @NonNull final String[] testCase,
460
            @NonNull final String fqn,
461
            @NonNull final String methodName,
462
            final boolean useRT,
463
            @NonNull final String retType,
464
            @NonNull final List<? extends String> paramTypes,
465
            @NonNull final Collection<? extends String> expected) throws Exception {
466
        final FileObject file = prepareTest(
467
            srcRoot,
468
            testCase[0],
469
            testCase[1],
470
            testCase[2]);
471
        final Collection<? extends String> res = Queries.query(
472
            file,
473
            new Function<Queries, Collection<? extends String>>(){
474
                @Override
475
                public Collection< ? extends String> apply(Queries param) throws QueryException {
476
                    return param.getMethodAnnotations(
477
                        fqn,
478
                        methodName,
479
                        useRT,
480
                        retType,
481
                        paramTypes == null ? null : paramTypes.toArray(new String[paramTypes.size()]));
482
                }
483
            });
484
        assertContentEquals(expected, res);
485
    }
486
487
    public void testModifyInterfaces() throws Exception {
488
        doTestModifyInterfaces(TEST_5,"org.me.test.Test5",
489
                Collections.singletonList("java.lang.Runnable"),
490
                Collections.<String>emptySet(),
491
                Collections.singletonList("java.lang.Runnable"));
492
        doTestModifyInterfaces(TEST_5,"org.me.test.Test5",
493
                Collections.singletonList("java.io.Serializable"),
494
                Collections.<String>emptySet(),
495
                Arrays.asList("java.lang.Runnable","java.io.Serializable"));
496
        doTestModifyInterfaces(TEST_5,"org.me.test.Test5",
497
                Collections.singletonList("java.io.Externalizable"),
498
                Collections.singletonList("java.io.Serializable"),
499
                Arrays.asList("java.lang.Runnable","java.io.Externalizable"));
500
        doTestModifyInterfaces(TEST_5,"org.me.test.Test5",
501
                Collections.<String>emptySet(),
502
                Arrays.asList("java.lang.Runnable","java.io.Externalizable"),
503
                Collections.<String>emptySet());
504
    }
505
506
    private void doTestModifyInterfaces(
507
        @NonNull final String[] testCase,
508
            @NonNull final String clz,
509
            @NonNull final Collection<? extends String> toAdd,
510
            @NonNull final Collection<? extends String> toRemove,
511
            @NonNull final Collection<? extends String> expected
512
            ) throws Exception {
513
        final FileObject file = prepareTest(
514
            srcRoot,
515
            testCase[0],
516
            testCase[1],
517
            testCase[2]);
518
        Updates.update(
519
            file,
520
            new Function<Updates, Boolean>(){
521
                @Override
522
                public Boolean apply(final Updates param) throws QueryException {
523
                        param.modifyInterfaces(
524
                            clz,
525
                            toAdd,
526
                            toRemove);
527
                        return true;
528
                }
529
            });
530
        final Collection< ? extends String> res = Queries.query(
531
            file,
532
            new Function<Queries, Collection<? extends String>>(){
533
                @Override
534
                public Collection<? extends String> apply(Queries param) throws QueryException {
535
                    return param.getInterfaces(clz);
536
                }
537
            });
538
        assertContentEquals(expected, res);
539
    }
540
541
    public void testSetSuperClass() throws Exception {
542
        doTestSetSuperClass(TEST_5,"org.me.test.Test5",
543
                "java.util.ArrayList",
544
                "java.util.ArrayList");
545
        doTestSetSuperClass(TEST_5,"org.me.test.Test5",
546
                "java.lang.Object",
547
                "java.lang.Object");
548
    }
549
550
    private void doTestSetSuperClass(
551
        @NonNull final String[] testCase,
552
        @NonNull final String clz,
553
        @NonNull final String superClz,
554
        @NonNull final String expected) throws Exception {
555
        final FileObject file = prepareTest(
556
            srcRoot,
557
            testCase[0],
558
            testCase[1],
559
            testCase[2]);
560
        Updates.update(
561
            file,
562
            new Function<Updates, Boolean>(){
563
                @Override
564
                public Boolean apply(final Updates param) throws QueryException {
565
                    param.setSuperClass(
566
                        clz,
567
                        superClz);
568
                    return true;
569
                }
570
            });
571
        final String res = Queries.query(
572
            file,
573
            new Function<Queries, String>(){
574
                @Override
575
                public String apply(Queries param) throws QueryException {
576
                    return param.getSuperClass(clz);
577
                }
578
            });
579
        assertEquals(expected, res);
580
    }
581
582
    public void testModifyMethodAnnotations() throws Exception {
583
        doTestModifyMethodAnnotations(TEST_5,"org.me.test.Test5","m1",false,
584
            "void",
585
             Collections.<String>emptyList(),
586
             Collections.singleton("java.lang.Override"),
587
             Collections.<String>emptyList(),
588
             Collections.singleton("java.lang.Override"));
589
        doTestModifyMethodAnnotations(TEST_5,"org.me.test.Test5","m1",false,
590
            "void",
591
             Collections.<String>emptyList(),
592
             Collections.singleton("java.lang.SuppressWarnings"),
593
             Collections.<String>emptyList(),
594
             Arrays.asList("java.lang.Override","java.lang.SuppressWarnings"));
595
        doTestModifyMethodAnnotations(TEST_5,"org.me.test.Test5","m1",false,
596
            "void",
597
             Collections.<String>emptyList(),
598
             Collections.<String>emptyList(),
599
             Collections.singleton("java.lang.SuppressWarnings"),
600
             Collections.singleton("java.lang.Override"));
601
        doTestModifyMethodAnnotations(TEST_5,"org.me.test.Test5","m1",false,
602
            "void",
603
             Collections.<String>emptyList(),
604
             Collections.<String>emptyList(),
605
             Collections.singleton("java.lang.Override"),
606
             Collections.<String>emptySet());
607
        doTestModifyMethodAnnotations(TEST_5,"org.me.test.Test5","m1",false,
608
            "void",
609
             Collections.<String>emptyList(),
610
             Arrays.asList("java.lang.Override","java.lang.SuppressWarnings"),
611
             Collections.<String>emptyList(),
612
             Arrays.asList("java.lang.Override","java.lang.SuppressWarnings"));
613
        doTestModifyMethodAnnotations(TEST_5,"org.me.test.Test5","m1",false,
614
            "void",
615
             Collections.<String>emptyList(),
616
             Collections.<String>emptyList(),
617
             Arrays.asList("java.lang.Override","java.lang.SuppressWarnings"),
618
             Collections.<String>emptySet());
619
    }
620
621
    private void doTestModifyMethodAnnotations(
622
            @NonNull final String[] testCase,
623
            @NonNull final String fqn,
624
            @NonNull final String methodName,
625
            final boolean useRT,
626
            @NonNull final String retType,
627
            @NonNull final List<? extends String> paramTypes,
628
            @NonNull final Collection<? extends String> toAdd,
629
            @NonNull final Collection<? extends String> toRemove,
630
            @NonNull final Collection<? extends String> expected) throws Exception {
631
        final FileObject file = prepareTest(
632
            srcRoot,
633
            testCase[0],
634
            testCase[1],
635
            testCase[2]);
636
        Updates.update(
637
            file,
638
            new Function<Updates, Boolean>(){
639
                @Override
640
                public Boolean apply(final Updates param) throws QueryException {
641
                    param.modifyMethodAnnotations(
642
                        fqn,
643
                        methodName,
644
                        useRT,
645
                        retType,
646
                        paramTypes.toArray(new String[paramTypes.size()]),
647
                        toAdd,
648
                        toRemove);
649
                    return true;
650
                }
651
            });
652
        final Collection<? extends String> res = Queries.query(
653
            file,
654
            new Function<Queries, Collection<? extends String>>(){
655
                @Override
656
                public Collection<? extends String> apply(Queries param) throws QueryException {
657
                    return param.getMethodAnnotations(
658
                        fqn,
659
                        methodName,
660
                        useRT,
661
                        retType,
662
                        paramTypes.toArray(new String[paramTypes.size()]));
663
                }
664
            });
665
        assertContentEquals(expected, res);
666
    }
667
668
    public void testRenameField() throws Exception {
669
        doTestRenameField(TEST_6,"org.me.test.Test6",
670
                "a",
671
                "b");
672
    }
673
674
    private void doTestRenameField(
675
            @NonNull final String[] testCase,
676
            @NonNull final String fqn,
677
            @NonNull final String oldFieldName,
678
            @NonNull final String newFieldName) throws Exception {
679
        final FileObject file = prepareTest(
680
            srcRoot,
681
            testCase[0],
682
            testCase[1],
683
            testCase[2]);
684
        Updates.update(
685
            file,
686
            new Function<Updates, Boolean>(){
687
                @Override
688
                public Boolean apply(final Updates param) throws QueryException {
689
                    param.renameField(
690
                        fqn,
691
                        oldFieldName,
692
                        newFieldName);
693
                    return true;
694
                }
695
            });
696
        final Collection<? extends String> res = Queries.query(
697
            file,
698
            new Function<Queries, Collection<? extends String>>(){
699
                @Override
700
                public Collection<? extends String> apply(Queries param) throws QueryException {
701
                    return param.getFieldNames(fqn, true, null);
702
                }
703
            });
704
        assertContentEquals(Collections.singleton(newFieldName), res);
705
    }
706
707
    protected final <T> void assertContentEquals(
708
            @NullAllowed final Collection<? extends T> expected,
709
            @NullAllowed final Collection<? extends T> result) {
710
        if (expected == null) {
711
            assertNull("Expected null but got: " + result ,result);
712
        } else {
713
            final Set<T> e = new HashSet<T>(expected);
714
            for (T r : result) {
715
                if (!e.remove(r)) {
716
                    throw new AssertionError("Expected: " + expected +" got:" + result);
717
                }
718
            }
719
            if (!e.isEmpty()) {
720
                throw new AssertionError("Expected: " + expected +" got:" + result);
721
            }
722
        }
723
    }
724
725
    protected final FileObject prepareTest(
726
            @NonNull final FileObject root,
727
            @NonNull final String pkg,
728
            @NonNull final String name,
729
            @NonNull final String content) throws IOException {
730
        if (Lookup.getDefault().lookup(QueriesController.class) == null) {
731
            throw new IllegalStateException("Run the ModelOperationsTest subclass in impl module.");
732
        }
733
        assert root != null;
734
        assert pkg != null;
735
        assert name != null;
736
        assert content != null;
737
        final String fileName = String.format("%s/%s.java",
738
            pkg.replace('.', '/'),
739
            name);
740
        FileObject fo = root.getFileObject(fileName);
741
        if (fo != null) {
742
            return fo;
743
        }
744
        fo = FileUtil.createData(
745
            srcRoot,
746
            fileName);
747
        final FileLock lock = fo.lock();
748
        try {
749
            final PrintWriter out = new PrintWriter (new OutputStreamWriter(fo.getOutputStream(lock)));
750
            try {
751
                out.print(content);
752
            } finally {
753
                out.close();
754
            }
755
        } finally {
756
            lock.releaseLock();
757
        }
758
        return fo;
759
    }
760
}
(-)a/java.source.queriesimpl/build.xml (+5 lines)
Line 0 Link Here
1
<?xml version="1.0" encoding="UTF-8"?>
2
<project basedir="." default="netbeans" name="java.source.queriesimpl">
3
    <description>Builds, tests, and runs the project org.netbeans.modules.java.source.queriesimpl</description>
4
    <import file="../nbbuild/templates/projectized.xml"/>
5
</project>
(-)a/java.source.queriesimpl/manifest.mf (+5 lines)
Line 0 Link Here
1
Manifest-Version: 1.0
2
OpenIDE-Module: org.netbeans.modules.java.source.queriesimpl
3
OpenIDE-Module-Localizing-Bundle: org/netbeans/modules/java/source/queriesimpl/Bundle.properties
4
OpenIDE-Module-Specification-Version: 1.0
5
(-)a/java.source.queriesimpl/nbproject/project.properties (+3 lines)
Line 0 Link Here
1
javac.source=1.6
2
javac.compilerargs=-Xlint -Xlint:-serial
3
requires.nb.javac=true
(-)a/java.source.queriesimpl/nbproject/project.xml (+91 lines)
Line 0 Link Here
1
<?xml version="1.0" encoding="UTF-8"?>
2
<project xmlns="http://www.netbeans.org/ns/project/1">
3
    <type>org.netbeans.modules.apisupport.project</type>
4
    <configuration>
5
        <data xmlns="http://www.netbeans.org/ns/nb-module-project/3">
6
            <code-name-base>org.netbeans.modules.java.source.queriesimpl</code-name-base>
7
            <module-dependencies>
8
                <dependency>
9
                    <code-name-base>org.netbeans.api.annotations.common</code-name-base>
10
                    <build-prerequisite/>
11
                    <compile-dependency/>
12
                    <run-dependency>
13
                        <release-version>1</release-version>
14
                        <specification-version>1.10</specification-version>
15
                    </run-dependency>
16
                </dependency>
17
                <dependency>
18
                    <code-name-base>org.netbeans.modules.java.source</code-name-base>
19
                    <build-prerequisite/>
20
                    <compile-dependency/>
21
                    <run-dependency>
22
                        <specification-version>0.81</specification-version>
23
                    </run-dependency>
24
                </dependency>
25
                <dependency>
26
                    <code-name-base>org.netbeans.modules.java.source.queries</code-name-base>
27
                    <build-prerequisite/>
28
                    <compile-dependency/>
29
                    <run-dependency>
30
                        <specification-version>1.0</specification-version>
31
                    </run-dependency>
32
                </dependency>
33
                <dependency>
34
                    <code-name-base>org.netbeans.modules.parsing.api</code-name-base>
35
                    <build-prerequisite/>
36
                    <compile-dependency/>
37
                    <run-dependency>
38
                        <release-version>1</release-version>
39
                        <specification-version>1.43</specification-version>
40
                    </run-dependency>
41
                </dependency>
42
                <dependency>
43
                    <code-name-base>org.openide.filesystems</code-name-base>
44
                    <build-prerequisite/>
45
                    <compile-dependency/>
46
                    <run-dependency>
47
                        <specification-version>7.48</specification-version>
48
                    </run-dependency>
49
                </dependency>
50
                <dependency>
51
                    <code-name-base>org.openide.util.lookup</code-name-base>
52
                    <build-prerequisite/>
53
                    <compile-dependency/>
54
                    <run-dependency>
55
                        <specification-version>8.9</specification-version>
56
                    </run-dependency>
57
                </dependency>
58
            </module-dependencies>
59
            <test-dependencies>
60
                <test-type>
61
                    <name>unit</name>
62
                    <test-dependency>
63
                        <code-name-base>org.netbeans.libs.junit4</code-name-base>
64
                        <compile-dependency/>
65
                    </test-dependency>
66
                    <test-dependency>
67
                        <code-name-base>org.netbeans.modules.editor.mimelookup</code-name-base>
68
                        <compile-dependency/>
69
                        <test/>
70
                    </test-dependency>
71
                    <test-dependency>
72
                        <code-name-base>org.netbeans.modules.java.source</code-name-base>
73
                        <recursive/>
74
                        <compile-dependency/>
75
                    </test-dependency>
76
                    <test-dependency>
77
                        <code-name-base>org.netbeans.modules.java.source.queries</code-name-base>
78
                        <compile-dependency/>
79
                        <test/>
80
                    </test-dependency>
81
                    <test-dependency>
82
                        <code-name-base>org.netbeans.modules.nbjunit</code-name-base>
83
                        <recursive/>
84
                        <compile-dependency/>
85
                    </test-dependency>
86
                </test-type>
87
            </test-dependencies>
88
            <public-packages/>
89
        </data>
90
    </configuration>
91
</project>
(-)a/java.source.queriesimpl/src/org/netbeans/modules/java/source/queriesimpl/Bundle.properties (+1 lines)
Line 0 Link Here
1
OpenIDE-Module-Name=Java Source Queries Implementation
(-)a/java.source.queriesimpl/src/org/netbeans/modules/java/source/queriesimpl/JavaOperationsImpl.java (+589 lines)
Line 0 Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2011 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
 *
40
 * Portions Copyrighted 2011 Sun Microsystems, Inc.
41
 */
42
package org.netbeans.modules.java.source.queriesimpl;
43
44
import com.sun.source.tree.AnnotationTree;
45
import com.sun.source.tree.ClassTree;
46
import com.sun.source.tree.CompilationUnitTree;
47
import com.sun.source.tree.ExpressionTree;
48
import com.sun.source.tree.IdentifierTree;
49
import com.sun.source.tree.MethodTree;
50
import com.sun.source.tree.ModifiersTree;
51
import com.sun.source.tree.Tree;
52
import com.sun.source.tree.Tree.Kind;
53
import com.sun.source.tree.VariableTree;
54
import com.sun.source.util.TreePath;
55
import com.sun.source.util.TreePathScanner;
56
import com.sun.source.util.Trees;
57
import java.io.IOException;
58
import java.util.ArrayList;
59
import java.util.Collection;
60
import java.util.Collections;
61
import java.util.HashSet;
62
import java.util.Iterator;
63
import java.util.List;
64
import java.util.Set;
65
import javax.lang.model.element.AnnotationMirror;
66
import javax.lang.model.element.Element;
67
import javax.lang.model.element.ElementKind;
68
import javax.lang.model.element.ExecutableElement;
69
import javax.lang.model.element.Modifier;
70
import javax.lang.model.element.TypeElement;
71
import javax.lang.model.element.VariableElement;
72
import javax.lang.model.type.DeclaredType;
73
import javax.lang.model.type.TypeKind;
74
import javax.lang.model.type.TypeMirror;
75
import javax.lang.model.util.ElementFilter;
76
import javax.lang.model.util.Types;
77
import org.netbeans.api.annotations.common.CheckForNull;
78
import org.netbeans.api.annotations.common.NonNull;
79
import org.netbeans.api.annotations.common.NullAllowed;
80
import org.netbeans.api.java.source.CompilationController;
81
import org.netbeans.api.java.source.ElementUtilities;
82
import org.netbeans.api.java.source.GeneratorUtilities;
83
import org.netbeans.api.java.source.JavaSource.Phase;
84
import org.netbeans.api.java.source.TreeMaker;
85
import org.netbeans.api.java.source.TreeUtilities;
86
import org.netbeans.api.java.source.WorkingCopy;
87
import org.netbeans.modules.java.source.queries.api.QueryException;
88
import org.netbeans.modules.java.source.queries.spi.ModelOperations;
89
import org.openide.filesystems.FileObject;
90
import org.openide.filesystems.FileUtil;
91
92
/**
93
 *
94
 * @author Tomas Zezula
95
 */
96
class JavaOperationsImpl implements ModelOperations {
97
98
    final CompilationController control;
99
100
    JavaOperationsImpl(@NonNull final CompilationController control) {
101
        assert control != null;
102
        this.control = control;
103
    }
104
105
    @Override
106
    @NonNull
107
    public Collection<? extends String> getTopLevelClasses(@NonNull final FileObject file) throws QueryException {
108
        try {
109
            control.toPhase(Phase.ELEMENTS_RESOLVED);
110
        } catch (IOException ioe) {
111
            throw new QueryException(ioe);
112
        }
113
        final Collection<? extends Element> topLevels = control.getTopLevelElements();
114
        final List<String> result = new ArrayList<String>(topLevels.size());
115
        for (Element topLevel : topLevels) {
116
            result.add(((TypeElement)topLevel).getQualifiedName().toString());
117
        }
118
        return result;
119
    }
120
121
    @Override
122
    public boolean isJavaBean(@NonNull final String cls) throws QueryException {
123
        final TypeElement clz = findClass(cls);
124
        if (clz != null && clz.getModifiers().contains(Modifier.PUBLIC)) {
125
            for (Element member : clz.getEnclosedElements()) {
126
                if (member.getKind() == ElementKind.CONSTRUCTOR &&
127
                    ((ExecutableElement)member).getParameters().isEmpty() &&
128
                    ((ExecutableElement)member).getModifiers().contains(Modifier.PUBLIC)) {
129
                    return true;
130
                }
131
            }
132
        }
133
        return false;
134
    }
135
136
    @Override
137
    public boolean isAvailable(@NonNull final String cls) throws QueryException {
138
        return findClass(cls) != null;
139
    }
140
141
    @Override
142
    @CheckForNull
143
    public String getSuperClass(@NonNull final String cls) throws QueryException {
144
        final TypeElement te = findClass(cls);
145
        if (te == null) {
146
            return null;
147
        }
148
        final TypeMirror superType = te.getSuperclass();
149
        if (superType.getKind() != TypeKind.DECLARED) {
150
            return null;
151
        }
152
        return ((TypeElement)((DeclaredType)superType).asElement()).getQualifiedName().toString();
153
    }
154
155
    @NonNull
156
    @Override
157
    public final Collection<? extends String> getInterfaces(@NonNull final String cls) throws QueryException {
158
        final TypeElement te = findClass(cls);
159
        if (te == null) {
160
            return null;
161
        }
162
        final List<? extends TypeMirror> interfaceTypes = te.getInterfaces();
163
        final List<String> result = new ArrayList<String>(interfaceTypes.size());
164
        for (TypeMirror tm : interfaceTypes) {
165
            if (tm.getKind() == TypeKind.DECLARED) {
166
                result.add(
167
                    ((TypeElement)((DeclaredType)tm).asElement()).getQualifiedName().toString());
168
            }
169
        }
170
        return Collections.unmodifiableCollection(result);
171
    }
172
173
    @Override
174
    @CheckForNull
175
    public String getClassBinaryName(@NonNull final String cls) throws QueryException {
176
        final TypeElement te = findClass(cls);
177
        return te == null ? null : ElementUtilities.getBinaryName(te);
178
    }
179
180
    @Override
181
    @NonNull
182
    public Collection<? extends String> getFieldNames(
183
            @NonNull final String clz,
184
            final boolean rt,
185
            @NullAllowed final String type) throws QueryException {
186
        final TypeElement te = findClass(clz);
187
        if (te == null) {
188
            return Collections.<String>emptyList();
189
        }
190
        final Types types = control.getTypes();
191
        TypeMirror tm = null;
192
        if (type != null) {
193
            final List<? extends TypeElement> topLevels = control.getTopLevelElements();
194
            tm = topLevels.isEmpty() ?
195
                null :
196
                control.getTreeUtilities().parseType(type, topLevels.get(0));
197
            if (tm == null) {
198
                return Collections.<String>emptyList();
199
            } else if (rt) {
200
                tm = types.erasure(tm);
201
            }
202
        }
203
        final Collection<String> result = new ArrayList<String>();
204
        for (VariableElement ve : ElementFilter.fieldsIn(te.getEnclosedElements())) {
205
            if (isSameType(types,tm,ve.asType(),rt)) {
206
                result.add(ve.getSimpleName().toString());
207
            }
208
        }
209
        return Collections.unmodifiableCollection(result);
210
    }
211
212
    @Override
213
    @NonNull
214
    public Collection<? extends String> getMethodNames(
215
            final @NonNull String clz,
216
            final boolean rt,
217
            final @NullAllowed String returnType,
218
            final @NullAllowed String... parameterTypes) throws QueryException {
219
        final List<? extends ExecutableElement> methods = getMethods(clz, null, rt, returnType, parameterTypes);
220
        final List<String> result = new ArrayList<String>(methods.size());
221
        for (ExecutableElement method : methods) {
222
            result.add(method.getSimpleName().toString());
223
        }
224
        return Collections.unmodifiableCollection(result);
225
    }
226
227
    @Override
228
    @NonNull
229
    public Collection<? extends String> getMethodAnnotations(
230
            @NonNull final String clz,
231
            @NonNull final String methodName,
232
            final boolean rt,
233
            @NonNull final String returnType,
234
            @NonNull final String... parameterTypes) throws QueryException {
235
        final List<? extends ExecutableElement> methods = getMethods(clz, null, rt, returnType, parameterTypes);
236
        if (methods.isEmpty()) {
237
            return Collections.<String>emptyList();
238
        } else {
239
            //Todo: if size > 1 => 2 methods with same signature (invalid source) use the first one
240
            final ExecutableElement method = methods.get(0);
241
            final List<String> result = new ArrayList<String>();
242
            for (AnnotationMirror ann : method.getAnnotationMirrors()) {
243
                if (ann.getAnnotationType().getKind() == TypeKind.DECLARED) {
244
                    result.add (((TypeElement)ann.getAnnotationType().asElement()).getQualifiedName().toString());
245
                }
246
            }
247
            return Collections.unmodifiableCollection(result);
248
        }
249
    }
250
251
    @Override
252
    public void modifyInterfaces(
253
        @NonNull final String clz,
254
        @NonNull final Collection<? extends String> toAdd,
255
        @NonNull final Collection<? extends String> toRemove) throws QueryException {
256
        if (!(control instanceof WorkingCopy)) {
257
            throw new IllegalStateException();
258
        }
259
        final WorkingCopy wcopy = (WorkingCopy) control;
260
        final TreePath mainClassTreePath = findClassInCompilationUnit(clz);
261
        if (mainClassTreePath == null) {
262
            throw new IllegalArgumentException("No class: " + clz + " in source: " +    //NOI18N
263
                    FileUtil.getFileDisplayName(control.getFileObject()));
264
        }
265
        final Element mainClassElm = wcopy.getTrees().getElement(mainClassTreePath);
266
        assert mainClassElm != null;
267
        ClassTree mainClassTree = (ClassTree) mainClassTreePath.getLeaf();
268
        final ClassTree origMainTree = mainClassTree;
269
        if (mainClassElm != null) {
270
            Set<String> actualInterfaces = new HashSet<String>();
271
            TreeMaker maker = wcopy.getTreeMaker();
272
            // first take the current interfaces and exclude the removed ones
273
            List<? extends TypeMirror> interfaces = ((TypeElement) mainClassElm).getInterfaces();
274
            for (int infIndex = interfaces.size() - 1; infIndex >= 0; infIndex--) {
275
                TypeMirror infMirror = interfaces.get(infIndex);
276
                TypeElement infElm = (TypeElement) wcopy.getTypes().asElement(infMirror);
277
                actualInterfaces.add(infElm.getQualifiedName().toString());
278
                if (toRemove.contains(infElm.getQualifiedName().toString())) {
279
                    mainClassTree = maker.removeClassImplementsClause(mainClassTree, infIndex);
280
                }
281
            }
282
            for (String name : toAdd) {
283
                if (!actualInterfaces.contains(name)) {
284
                    TypeElement inf2add = wcopy.getElements().getTypeElement(name);
285
                    ExpressionTree infTree2add = inf2add != null
286
                            ? maker.QualIdent(inf2add)
287
                            : maker.Identifier(name);
288
                    mainClassTree = maker.addClassImplementsClause(mainClassTree, infTree2add);
289
                }
290
            }
291
            if (origMainTree != mainClassTree) {
292
                wcopy.rewrite(origMainTree, mainClassTree);
293
            }
294
        }
295
    }
296
297
    @Override
298
    public void setSuperClass(
299
            @NonNull final String clz,
300
            @NonNull final String superClz) throws QueryException {
301
        if (!(control instanceof WorkingCopy)) {
302
            throw new IllegalStateException();
303
        }
304
        final WorkingCopy wcopy = (WorkingCopy) control;
305
        final TreePath mainClassTreePath = findClassInCompilationUnit(clz);
306
        if (mainClassTreePath == null) {
307
            throw new IllegalArgumentException("No class: " + clz + " in source: " +    //NOI18N
308
                    FileUtil.getFileDisplayName(control.getFileObject()));
309
        }
310
        final Element mainClassElm = wcopy.getTrees().getElement(mainClassTreePath);
311
        assert mainClassElm != null;
312
        ClassTree mainClassTree = (ClassTree) mainClassTreePath.getLeaf();
313
        final ClassTree origMainTree = mainClassTree;
314
        if (mainClassElm != null) {
315
            final TreeMaker maker = wcopy.getTreeMaker();
316
            ExpressionTree superClsTree = null;
317
            if (!Object.class.getName().equals(superClz)){
318
                final TypeElement inf2add = wcopy.getElements().getTypeElement(superClz);
319
                superClsTree = inf2add != null
320
                    ? maker.QualIdent(inf2add)
321
                    : maker.Identifier(superClz);
322
            }
323
            mainClassTree = maker.setExtends(mainClassTree,superClsTree);
324
            if (origMainTree != mainClassTree) {
325
                wcopy.rewrite(origMainTree, mainClassTree);
326
            }
327
        }
328
    }
329
330
    @Override
331
    public void modifyMethodAnnotations(
332
        @NonNull final String clz,
333
        @NonNull final String methodName,
334
        final boolean rt,
335
        @NonNull final String returnType,
336
        @NonNull final String[] parameterTypes,
337
        @NonNull Collection<? extends String> toAdd,
338
        @NonNull Collection<? extends String> toRemove) throws QueryException {
339
        if (!(control instanceof WorkingCopy)) {
340
            throw new IllegalStateException();
341
        }
342
        final WorkingCopy wcopy = (WorkingCopy) control;
343
        final List<? extends ExecutableElement> methods = getMethods(clz, null, rt, returnType, parameterTypes);
344
        if (methods.isEmpty()) {
345
            throw new IllegalArgumentException("No method: " + clz + "." + methodName + " in source: " +    //NOI18N
346
                FileUtil.getFileDisplayName(control.getFileObject()));
347
        } else {
348
            //Todo: if size > 1 => 2 methods with same signature (invalid source) use the first one
349
            final ExecutableElement method = methods.get(0);
350
            final TreePath methodTreePath = control.getTrees().getPath(method);
351
            if (methodTreePath == null) {
352
                throw new IllegalArgumentException("No method: " + clz + "." + methodName + " in source: " +    //NOI18N
353
                FileUtil.getFileDisplayName(control.getFileObject()));
354
            }
355
            final TreeMaker maker = wcopy.getTreeMaker();
356
            final MethodTree methodTree = (MethodTree) methodTreePath.getLeaf();
357
            ModifiersTree modTree = methodTree.getModifiers();
358
            final ModifiersTree origModTree = modTree;
359
            final Set<String> actualAnnotations = new HashSet<String>();
360
            for (AnnotationTree annotation : modTree.getAnnotations()) {
361
                final Element ae = control.getTrees().getElement(
362
                    TreePath.getPath(methodTreePath.getCompilationUnit(),
363
                    annotation.getAnnotationType()));
364
                if (ae != null &&
365
                   (ae.getKind().isClass() || ae.getKind().isInterface())) {
366
                    final String afqn = ((TypeElement)ae).getQualifiedName().toString();
367
                    actualAnnotations.add(afqn);
368
                    if (toRemove.contains(afqn)) {
369
                        modTree = maker.removeModifiersAnnotation(modTree, annotation);
370
                    }
371
                }
372
            }
373
            for (String afqn : toAdd) {
374
                if (!actualAnnotations.contains(afqn)) {
375
                    TypeElement ann2add = wcopy.getElements().getTypeElement(afqn);
376
                    ExpressionTree annTree2add = ann2add != null
377
                            ? maker.QualIdent(ann2add)
378
                            : maker.Identifier(afqn);
379
                    final AnnotationTree annotation = maker.Annotation(
380
                            annTree2add,
381
                            Collections.<ExpressionTree>emptyList());
382
                    modTree = maker.addModifiersAnnotation(modTree, annotation);
383
                }
384
            }
385
            if (origModTree != modTree) {
386
                wcopy.rewrite(origModTree, modTree);
387
            }
388
        }
389
    }
390
391
    @Override
392
    public void renameField(
393
        @NonNull final String clz,
394
        @NonNull final String oldName,
395
        @NonNull final String newName)  throws QueryException {
396
        final WorkingCopy wcopy = (WorkingCopy) control;
397
        final TypeElement te = findClass(clz);
398
        if (te == null) {
399
            throw new IllegalArgumentException("No class: " + clz + " in source: " +    //NOI18N
400
                FileUtil.getFileDisplayName(control.getFileObject()));
401
        }
402
        VariableElement field = null;
403
        for (VariableElement ve : ElementFilter.fieldsIn(te.getEnclosedElements())) {
404
            if (oldName.contentEquals(ve.getSimpleName())) {
405
                field = ve;
406
                break;
407
            }
408
        }
409
        if (field == null) {
410
            throw new IllegalArgumentException("No field: " + clz +"."+oldName + " in source: " +    //NOI18N
411
                FileUtil.getFileDisplayName(control.getFileObject()));
412
        }
413
        final TreePath fieldPath = wcopy.getTrees().getPath(field);
414
        if (fieldPath == null) {
415
            throw new IllegalArgumentException("No field: " + clz +"."+oldName + " in source: " +    //NOI18N
416
                FileUtil.getFileDisplayName(control.getFileObject()));
417
        }
418
        final VariableTree oldVarTree = (VariableTree) fieldPath.getLeaf();
419
        final VariableTree newVarTree = wcopy.getTreeMaker().Variable(
420
                oldVarTree.getModifiers(),
421
                newName,
422
                oldVarTree.getType(),
423
                oldVarTree.getInitializer());
424
        wcopy.rewrite(oldVarTree, newVarTree);
425
    }
426
427
    @Override
428
    public void fixImports(
429
            final FileObject file,
430
            final Collection<? extends String> requiredFQNs) throws QueryException {
431
        if (!(control instanceof WorkingCopy)) {
432
            throw new IllegalStateException();
433
        }
434
        final WorkingCopy wcopy = (WorkingCopy) control;
435
        try {
436
            control.toPhase(Phase.RESOLVED);
437
        } catch (IOException ioe) {
438
            throw new QueryException(ioe);
439
        }
440
        final CompilationUnitTree cu = wcopy.getCompilationUnit();
441
        final Trees trees = wcopy.getTrees();
442
        final GeneratorUtilities utils = GeneratorUtilities.get(wcopy);
443
        final List<Tree> toImport = new ArrayList<Tree>();
444
        final TreePathScanner<Void,Void> scanner = new TreePathScanner<Void, Void>(){
445
            @Override
446
            public Void visitIdentifier(IdentifierTree node, Void p) {
447
                final TreePath select = findSelect(getCurrentPath());
448
                if (select.getLeaf() != node) {
449
                    final Element e = trees.getElement(select);
450
                    if (e != null &&
451
                       (e.getKind().isInterface() || e.getKind().isClass()) &&
452
                       requiredFQNs.contains(((TypeElement)e).getQualifiedName().toString())) {
453
                       toImport.add(select.getLeaf());
454
                    }
455
                }
456
                return super.visitIdentifier(node, p);
457
            }
458
459
            private TreePath findSelect(final TreePath path) {
460
                if (path.getParentPath().getLeaf().getKind() != Kind.MEMBER_SELECT) {
461
                    return path;
462
                }
463
                return findSelect(path.getParentPath());
464
            }
465
        };
466
        scanner.scan(cu, null);
467
        for (Tree tree : toImport) {
468
            wcopy.rewrite(tree, utils.importFQNs(tree));
469
        }
470
    }
471
472
    private List<? extends ExecutableElement> getMethods(
473
            final @NonNull String clz,
474
            final @NullAllowed String methodName,
475
            final boolean rt,
476
            final @NullAllowed String returnType,
477
            final @NullAllowed String... parameterTypes) throws QueryException {
478
        final TypeElement te = findClass(clz);
479
        if (te == null) {
480
            return Collections.<ExecutableElement>emptyList();
481
        }
482
        final TreeUtilities treeUtils = control.getTreeUtilities();
483
        final Types types = control.getTypes();
484
        final List<? extends TypeElement> topLevels = control.getTopLevelElements();
485
        if (topLevels.isEmpty()) {
486
            return Collections.<ExecutableElement>emptyList();
487
        }
488
        TypeMirror rType = null;
489
        List<TypeMirror> pTypes = null;
490
        if (returnType != null) {
491
            rType = treeUtils.parseType(
492
                returnType,
493
                topLevels.get(0));
494
            if (rType == null) {
495
                return Collections.<ExecutableElement>emptyList();
496
            } else if (rt) {
497
                rType = types.erasure(rType);
498
            }
499
        }
500
        if (parameterTypes != null) {
501
            pTypes = new ArrayList<TypeMirror>(parameterTypes.length + 1);
502
            for (final String parameterType : parameterTypes) {
503
                TypeMirror tm = treeUtils.parseType(
504
                    parameterType,
505
                    topLevels.get(0));
506
                if (tm == null) {
507
                    return Collections.<ExecutableElement>emptyList();
508
                } else if (rt) {
509
                    tm = types.erasure(tm);
510
                }
511
                pTypes.add(tm);
512
            }
513
        }
514
        final List<ExecutableElement> result = new ArrayList<ExecutableElement>();
515
nextM:  for (ExecutableElement me : ElementFilter.methodsIn(te.getEnclosedElements())) {
516
            if (methodName != null && methodName.contentEquals(me.getSimpleName())) {
517
                continue nextM;
518
            }
519
            if (pTypes != null) {
520
                final List<? extends VariableElement> params = me.getParameters();
521
                if (params.size() != pTypes.size()) {
522
                    continue nextM;
523
                }
524
                final Iterator<? extends VariableElement> paramsIt = params.iterator();
525
                final Iterator<? extends TypeMirror> pTypesIt = pTypes.iterator();
526
                for (;paramsIt.hasNext();) {
527
                    if (!isSameType(types, pTypesIt.next(), paramsIt.next().asType(), rt)) {
528
                        continue nextM;
529
                    }
530
                }
531
            }
532
            if (!isSameType(types, rType, me.getReturnType(), rt)) {
533
                continue nextM;
534
            }
535
            result.add(me);
536
        }
537
        return result;
538
    }
539
540
    private TypeElement findClass(
541
            @NonNull final String clz) throws QueryException {
542
        try {
543
            control.toPhase(Phase.ELEMENTS_RESOLVED);
544
        } catch (IOException ioe) {
545
            throw new QueryException(ioe);
546
        }
547
        return control.getElements().getTypeElement(clz);
548
    }
549
550
    private TreePath findClassInCompilationUnit(
551
            @NonNull final String clz) throws QueryException {
552
        try {
553
            control.toPhase(Phase.ELEMENTS_RESOLVED);
554
        } catch (IOException ioe) {
555
            throw new QueryException(ioe);
556
        }
557
        final Trees trees = control.getTrees();
558
        final TreePathScanner<TreePath,Void> visitor = new TreePathScanner<TreePath, Void>() {
559
            @Override
560
            public TreePath visitClass(ClassTree node, Void p) {
561
                final Element el = trees.getElement(getCurrentPath());
562
                if (el != null &&
563
                   (el.getKind().isClass() || el.getKind().isInterface()) &&
564
                   clz.contentEquals(((TypeElement)el).getQualifiedName())) {
565
                    return getCurrentPath();
566
                } else {
567
                    return super.visitClass(node, p);
568
                }
569
            }
570
            @Override
571
            public TreePath visitMethod(MethodTree node, Void p) {
572
                return null;
573
            }
574
        };
575
        return visitor.scan(control.getCompilationUnit(), null);
576
    }
577
578
    private static boolean isSameType (
579
            @NonNull Types types,
580
            @NullAllowed final TypeMirror t1,
581
            @NonNull final TypeMirror t2,
582
            final boolean rawType) {
583
        return t1 == null ||
584
            types.isSameType(
585
                t1,
586
                rawType ? types.erasure(t2) : t2);
587
    }
588
589
}
(-)a/java.source.queriesimpl/src/org/netbeans/modules/java/source/queriesimpl/QueriesControllerImpl.java (+118 lines)
Line 0 Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2011 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
 *
40
 * Portions Copyrighted 2011 Sun Microsystems, Inc.
41
 */
42
package org.netbeans.modules.java.source.queriesimpl;
43
44
import java.io.IOException;
45
import org.netbeans.api.annotations.common.NonNull;
46
import org.netbeans.api.java.source.CompilationController;
47
import org.netbeans.api.java.source.JavaSource;
48
import org.netbeans.api.java.source.ModificationResult;
49
import org.netbeans.api.java.source.Task;
50
import org.netbeans.api.java.source.WorkingCopy;
51
import org.netbeans.modules.java.source.queries.api.QueryException;
52
import org.netbeans.modules.java.source.queries.api.Queries;
53
import org.netbeans.modules.java.source.queries.api.Updates;
54
import org.netbeans.modules.java.source.queries.spi.QueriesController;
55
import org.openide.filesystems.FileObject;
56
import org.openide.util.lookup.ServiceProvider;
57
58
/**
59
 *
60
 * @author Tomas Zezula
61
 */
62
@ServiceProvider(service=QueriesController.class)
63
public class QueriesControllerImpl implements QueriesController {
64
65
    @Override
66
    public <R> R runQuery(@NonNull Context<Queries,R> ctx) throws QueryException {
67
        final FileObject file = ctx.getFile();
68
        assert file != null;
69
        final JavaSource src = JavaSource.forFileObject(file);
70
        assert src != null;
71
        final QueryTask<CompilationController,Queries,R> qt =
72
            new QueryTask<CompilationController, Queries,R>(ctx);
73
        try {
74
            src.runUserActionTask(qt, true);
75
        } catch (IOException ioe) {
76
            throw new QueryException(ioe);
77
        }
78
        return qt.getResult();
79
    }
80
81
    @Override
82
    public void runUpdate(@NonNull Context<Updates,Boolean> ctx) throws QueryException {
83
        final FileObject file = ctx.getFile();
84
        assert file != null;
85
        final JavaSource src = JavaSource.forFileObject(file);
86
        assert src != null;
87
        final QueryTask<WorkingCopy, Updates, Boolean> qt =
88
                new QueryTask<WorkingCopy, Updates, Boolean>(ctx);
89
        try {
90
            final ModificationResult result = src.runModificationTask(qt);
91
            if (qt.getResult() == Boolean.TRUE) {
92
                result.commit();
93
            }
94
        } catch (IOException ioe) {
95
            throw new QueryException(ioe);
96
        }
97
    }
98
99
    private static class QueryTask<C extends CompilationController, P extends Queries, R> implements Task<C> {
100
101
        private final Context<P,R> ctx;
102
        private R result;
103
104
        private QueryTask(@NonNull final Context<P,R> ctx) {
105
            assert ctx != null;
106
            this.ctx = ctx;
107
        }
108
109
        @Override
110
        public void run(C parameter) throws Exception {
111
            result = ctx.execute(new JavaOperationsImpl(parameter));
112
        }
113
114
        public R getResult() {
115
            return result;
116
        }
117
    }
118
}
(-)a/java.source.queriesimpl/test/unit/src/org/netbeans/modules/java/source/queriesimpl/JavaOperationsImplTest.java (+218 lines)
Line 0 Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2011 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
 *
40
 * Portions Copyrighted 2011 Sun Microsystems, Inc.
41
 */
42
package org.netbeans.modules.java.source.queriesimpl;
43
44
import com.sun.source.tree.IdentifierTree;
45
import com.sun.source.tree.Tree;
46
import com.sun.source.tree.Tree.Kind;
47
import com.sun.source.util.TreePath;
48
import com.sun.source.util.TreePathScanner;
49
import java.io.File;
50
import java.net.URL;
51
import java.util.Arrays;
52
import java.util.Collection;
53
import java.util.HashSet;
54
import java.util.Set;
55
import javax.lang.model.element.Element;
56
import javax.lang.model.element.TypeElement;
57
import junit.framework.Test;
58
import junit.framework.TestSuite;
59
import org.netbeans.api.annotations.common.NonNull;
60
import org.netbeans.api.editor.mimelookup.MimePath;
61
import org.netbeans.api.editor.mimelookup.test.MockMimeLookup;
62
import org.netbeans.api.java.classpath.ClassPath;
63
import org.netbeans.api.java.source.CompilationController;
64
import org.netbeans.api.java.source.JavaSource;
65
import org.netbeans.api.java.source.Task;
66
import org.netbeans.junit.MockServices;
67
import org.netbeans.junit.NbTestSuite;
68
import org.netbeans.modules.java.source.parsing.JavacParserFactory;
69
import org.netbeans.modules.java.source.queries.api.Function;
70
import org.netbeans.modules.java.source.queries.api.QueryException;
71
import org.netbeans.modules.java.source.queries.api.Updates;
72
import org.netbeans.modules.java.source.queries.spi.ModelOperationsTest;
73
import org.netbeans.modules.parsing.impl.indexing.CacheFolder;
74
import org.netbeans.spi.java.classpath.ClassPathProvider;
75
import org.netbeans.spi.java.classpath.support.ClassPathSupport;
76
import org.openide.filesystems.FileObject;
77
import org.openide.filesystems.FileUtil;
78
/**
79
 *
80
 * @author Tomas Zezula
81
 */
82
public class JavaOperationsImplTest extends ModelOperationsTest {
83
84
    private static final String[] TEST_7 = {
85
        "org.me.test",
86
        "Test7.java",
87
        "package org.me.test;\n"+
88
        "public class Test7{\n"+
89
        "    java.util.Map<String,java.lang.String> m = new java.util.HashMap<String,java.lang.String>();\n"+
90
        "    java.util.Map<String,String> call(final java.util.List<String> l){\n"+
91
        "    final java.util.Map<String,String> res = new java.util.HashMap<String,String>(m);\n"+
92
        "    final java.util.Iterator<java.util.Map.Entry<String,String>> it = res.entrySet().iterator();\n"+
93
        "    final java.util.Map.Entry<String,String> e = it.next();\n"+
94
        "    return res;\n"+
95
        "    }\n"+
96
        "}"
97
    };
98
99
100
    public JavaOperationsImplTest(final String name) {
101
        super(name);
102
    }
103
104
    public static Test suite() {
105
        TestSuite suite = new NbTestSuite();
106
        suite.addTest(new JavaOperationsImplTest("testGetTopLevelClasses"));
107
        suite.addTest(new JavaOperationsImplTest("testIsJavaBean"));
108
        suite.addTest(new JavaOperationsImplTest("testIsAvialable"));
109
        suite.addTest(new JavaOperationsImplTest("testGetSuperClass"));
110
        suite.addTest(new JavaOperationsImplTest("testGetInterfaces"));
111
        suite.addTest(new JavaOperationsImplTest("testGetBinaryName"));
112
        suite.addTest(new JavaOperationsImplTest("testGetFieldNames"));
113
        suite.addTest(new JavaOperationsImplTest("testGetMethodNames"));
114
        suite.addTest(new JavaOperationsImplTest("testGetMethodAnnotations"));
115
        suite.addTest(new JavaOperationsImplTest("testModifyInterfaces"));
116
        suite.addTest(new JavaOperationsImplTest("testSetSuperClass"));
117
        suite.addTest(new JavaOperationsImplTest("testModifyMethodAnnotations"));
118
        suite.addTest(new JavaOperationsImplTest("testRenameField"));
119
        suite.addTest(new JavaOperationsImplTest("testFixImports"));
120
        return suite;
121
    }
122
123
    @Override
124
    protected void setUp() throws Exception {
125
        super.setUp();
126
        File cacheFolder = new File (getWorkDir(), "cache"); //NOI18N
127
        cacheFolder.mkdirs();
128
        CacheFolder.setCacheFolder(FileUtil.toFileObject(cacheFolder));
129
        CPProvider.srcPath = ClassPathSupport.createClassPath(srcRoot);
130
        CPProvider.bootPath = ClassPathSupport.createClassPath(System.getProperty("sun.boot.class.path"));
131
        CPProvider.compilePath = ClassPathSupport.createClassPath(new URL[0]);
132
        MockServices.setServices(CPProvider.class);
133
        MockMimeLookup.setInstances(MimePath.parse("text/x-java"), new JavacParserFactory());
134
    }
135
136
137
    public void testFixImports() throws Exception {
138
        doTestFixImports(TEST_7, Arrays.asList("java.util.List","java.util.Map","java.lang.String"));
139
    }
140
141
    private void doTestFixImports(
142
            @NonNull final String[] testCase,
143
            @NonNull final Collection< ? extends String> requiredFQNs) throws Exception {
144
        final FileObject file = prepareTest(
145
            srcRoot,
146
            testCase[0],
147
            testCase[1],
148
            testCase[2]);
149
        Updates.update(
150
            file,
151
            new Function<Updates, Boolean>(){
152
                @Override
153
                public Boolean apply(final Updates param) throws QueryException {
154
                    param.fixImports(requiredFQNs);
155
                    return true;
156
                }
157
            });
158
        final Set<String> fqns = new HashSet<String>();
159
        final JavaSource src = JavaSource.forFileObject(file);
160
        src.runUserActionTask(new Task<CompilationController>() {
161
            @Override
162
            public void run(final CompilationController parameter) throws Exception {
163
                parameter.toPhase(JavaSource.Phase.RESOLVED);
164
                final TreePathScanner<Void,Void> scanner = new TreePathScanner<Void, Void>(){
165
                    @Override
166
                    public Void visitIdentifier(IdentifierTree node, Void p) {
167
                        final TreePath select = findSelect(getCurrentPath());
168
                        if (select.getLeaf() != node) {
169
                            final Element e = parameter.getTrees().getElement(select);
170
                            if (e != null &&
171
                               (e.getKind().isInterface() || e.getKind().isClass())) {
172
                                fqns.add(((TypeElement)e).getQualifiedName().toString());
173
                            }
174
                        }
175
                        return super.visitIdentifier(node, p);
176
                    }
177
178
                    private TreePath findSelect(final TreePath path) {
179
                        if (path.getParentPath().getLeaf().getKind() != Kind.MEMBER_SELECT) {
180
                            return path;
181
                        }
182
                        return findSelect(path.getParentPath());
183
                    }
184
                };
185
                for (Tree tree : parameter.getCompilationUnit().getTypeDecls()) {
186
                    scanner.scan(TreePath.getPath(
187
                        parameter.getCompilationUnit(),tree), null);
188
                }
189
            }
190
        }, true);
191
        fqns.retainAll(requiredFQNs);
192
        assertTrue(fqns.isEmpty());
193
    }
194
195
    public static class CPProvider implements ClassPathProvider {
196
        private static ClassPath srcPath;
197
        private static ClassPath bootPath;
198
        private static ClassPath compilePath;
199
        @Override
200
        public ClassPath findClassPath(
201
                FileObject file,
202
                String type) {
203
            for (FileObject srcRoot : srcPath.getRoots()) {
204
                if (srcRoot.equals(file) || FileUtil.isParentOf(srcRoot, file)) {
205
                    if (type == ClassPath.SOURCE) {
206
                        return srcPath;
207
                    } else if (type == ClassPath.BOOT) {
208
                        return bootPath;
209
                    } else if (type == ClassPath.COMPILE) {
210
                        return compilePath;
211
                    }
212
                }
213
            }
214
            return null;
215
        }
216
    }
217
218
}
(-)a/nbbuild/javadoctools/links.xml (+1 lines)
Lines 204-206 Link Here
204
<link href="${javadoc.docs.org-netbeans-modules-autoupdate-ui}" offline="true" packagelistloc="${netbeans.javadoc.dir}/org-netbeans-modules-autoupdate-ui"/>
204
<link href="${javadoc.docs.org-netbeans-modules-autoupdate-ui}" offline="true" packagelistloc="${netbeans.javadoc.dir}/org-netbeans-modules-autoupdate-ui"/>
205
<link href="${javadoc.docs.org-netbeans-modules-php-project}" offline="true" packagelistloc="${netbeans.javadoc.dir}/org-netbeans-modules-php-project"/>
205
<link href="${javadoc.docs.org-netbeans-modules-php-project}" offline="true" packagelistloc="${netbeans.javadoc.dir}/org-netbeans-modules-php-project"/>
206
<link href="${javadoc.docs.org-netbeans-api-progress-transactional}" offline="true" packagelistloc="${netbeans.javadoc.dir}/org-netbeans-api-progress-transactional"/>
206
<link href="${javadoc.docs.org-netbeans-api-progress-transactional}" offline="true" packagelistloc="${netbeans.javadoc.dir}/org-netbeans-api-progress-transactional"/>
207
<link href="${javadoc.docs.org-netbeans-modules-java-source-queries}" offline="true" packagelistloc="${netbeans.javadoc.dir}/org-netbeans-modules-java-source-queries"/>
(-)a/nbbuild/javadoctools/properties.xml (+1 lines)
Lines 202-204 Link Here
202
<property name="javadoc.docs.org-netbeans-modules-autoupdate-ui" value="${javadoc.web.root}/org-netbeans-modules-autoupdate-ui"/>
202
<property name="javadoc.docs.org-netbeans-modules-autoupdate-ui" value="${javadoc.web.root}/org-netbeans-modules-autoupdate-ui"/>
203
<property name="javadoc.docs.org-netbeans-modules-php-project" value="${javadoc.web.root}/org-netbeans-modules-php-project"/>
203
<property name="javadoc.docs.org-netbeans-modules-php-project" value="${javadoc.web.root}/org-netbeans-modules-php-project"/>
204
<property name="javadoc.docs.org-netbeans-api-progress-transactional" value="${javadoc.web.root}/org-netbeans-api-progress-transactional"/>
204
<property name="javadoc.docs.org-netbeans-api-progress-transactional" value="${javadoc.web.root}/org-netbeans-api-progress-transactional"/>
205
<property name="javadoc.docs.org-netbeans-modules-java-source-queries" value="${javadoc.web.root}/org-netbeans-modules-java-source-queries"/>
(-)a/nbbuild/javadoctools/replaces.xml (+1 lines)
Lines 202-204 Link Here
202
<replacefilter token="@org-netbeans-modules-autoupdate-ui@" value="${javadoc.docs.org-netbeans-modules-autoupdate-ui}"/>
202
<replacefilter token="@org-netbeans-modules-autoupdate-ui@" value="${javadoc.docs.org-netbeans-modules-autoupdate-ui}"/>
203
<replacefilter token="@org-netbeans-modules-php-project@" value="${javadoc.docs.org-netbeans-modules-php-project}"/>
203
<replacefilter token="@org-netbeans-modules-php-project@" value="${javadoc.docs.org-netbeans-modules-php-project}"/>
204
<replacefilter token="@org-netbeans-api-progress-transactional@" value="${javadoc.docs.org-netbeans-api-progress-transactional}"/>
204
<replacefilter token="@org-netbeans-api-progress-transactional@" value="${javadoc.docs.org-netbeans-api-progress-transactional}"/>
205
<replacefilter token="@org-netbeans-modules-java-source-queries@" value="${javadoc.docs.org-netbeans-modules-java-source-queries}"/>

Return to bug 199405