~testplan-team/testplan/source-collection

« back to all changes in this revision

Viewing changes to htmlunit-2.6/src/test/java/com/gargoylesoftware/htmlunit/CodeChecker.java

  • Committer: edA-qa mort-ora-y
  • Date: 2010-04-07 10:54:57 UTC
  • Revision ID: eda-qa@disemia.com-20100407105457-g46bvbsrjqtjujab
updating hmltunit src

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (c) 2002-2009 Gargoyle Software Inc.
 
3
 *
 
4
 * Licensed under the Apache License, Version 2.0 (the "License");
 
5
 * you may not use this file except in compliance with the License.
 
6
 * You may obtain a copy of the License at
 
7
 * http://www.apache.org/licenses/LICENSE-2.0
 
8
 *
 
9
 * Unless required by applicable law or agreed to in writing, software
 
10
 * distributed under the License is distributed on an "AS IS" BASIS,
 
11
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 
12
 * See the License for the specific language governing permissions and
 
13
 * limitations under the License.
 
14
 */
 
15
package com.gargoylesoftware.htmlunit;
 
16
 
 
17
/**
 
18
 * Test of coding style using Eclipse JDT.
 
19
 * Currently checks for missing @Override annotations.
 
20
 *
 
21
 * To run it, you need:
 
22
 * <ul>
 
23
 *   <li>org.eclipse.core.contenttype_x.jar</li>
 
24
 *   <li>org.eclipse.core.jobs_x.jar</li>
 
25
 *   <li>org.eclipse.core.resources_x.jar</li>
 
26
 *   <li>org.eclipse.core.runtime_x.jar</li>
 
27
 *   <li>org.eclipse.equinox.preferences_x.jar</li>
 
28
 *   <li>org.eclipse.osgi_x.jar</li>
 
29
 * </ul>
 
30
 *
 
31
 * @version $Revision: 4833 $
 
32
 * @author Ahmed Ashour
 
33
 */
 
34
public class CodeChecker {
 
35
 
 
36
    /*
 
37
    private List<String> errors_ = new ArrayList<String>();
 
38
    private ASTParser parser_ = ASTParser.newParser(AST.JLS3);
 
39
 
 
40
    @After
 
41
    public void after() {
 
42
        final StringBuilder sb = new StringBuilder();
 
43
        for (final String error : errors_) {
 
44
            sb.append("\n" + error);
 
45
        }
 
46
 
 
47
        final int errorsNumber = errors_.size();
 
48
        if (errorsNumber == 1) {
 
49
            fail("CodeChecker error: " + sb);
 
50
        }
 
51
        else if (errorsNumber > 1) {
 
52
            fail("CodeChecker " + errorsNumber + " errors: " + sb);
 
53
        }
 
54
    }
 
55
 
 
56
    private void addFailure(final String error) {
 
57
        errors_.add(error);
 
58
    }
 
59
 
 
60
    @Test
 
61
    public void codeChecker() throws Exception {
 
62
        process(new File("src/main/java"));
 
63
        process(new File("src/test/java"));
 
64
    }
 
65
 
 
66
    private void process(final File dir) throws Exception {
 
67
        for (final File file : dir.listFiles()) {
 
68
            if (file.isDirectory() && !file.getName().equals(".svn")) {
 
69
                process(file);
 
70
            }
 
71
            else {
 
72
                if (file.getName().endsWith(".java")) {
 
73
                    final List<String> lines = CodeStyleTest.getLines(file);
 
74
                    checkOverride(lines);
 
75
                }
 
76
            }
 
77
        }
 
78
    }
 
79
 
 
80
    / **
 
81
     * Checks if the given file has any missing @Override annotation.
 
82
     *
 
83
     * @param lines lines
 
84
     * @throws Exception If an error occurs
 
85
     * /
 
86
    private void checkOverride(final List<String> lines) throws Exception {
 
87
        final CharArrayWriter writer = new CharArrayWriter();
 
88
        for (final String line : lines) {
 
89
            writer.write(line);
 
90
            writer.write("\n");
 
91
        }
 
92
        parser_.setSource(writer.toCharArray());
 
93
        final CompilationUnit cu = (CompilationUnit) parser_.createAST(null);
 
94
 
 
95
        for (final Object type : cu.types()) {
 
96
            if (type instanceof TypeDeclaration) {
 
97
                checkOverride((TypeDeclaration) type);
 
98
            }
 
99
        }
 
100
    }
 
101
 
 
102
    private void checkOverride(final TypeDeclaration type) throws Exception {
 
103
        for (final TypeDeclaration tt : type.getTypes()) {
 
104
            checkOverride(tt);
 
105
        }
 
106
        for (final MethodDeclaration method : type.getMethods()) {
 
107
            boolean isPrivate = false;
 
108
            for (final Object m : method.modifiers()) {
 
109
                if (m instanceof Modifier && ((Modifier) m).isPrivate()) {
 
110
                    isPrivate = true;
 
111
                    break;
 
112
                }
 
113
            }
 
114
            if (!isPrivate && !method.isConstructor() && !hasOverride(method) && shouldOverride(method)) {
 
115
                final String className = getFullyQualifiedName((TypeDeclaration) method.getParent()).replace('$', '.');
 
116
                addFailure("@Override is not defined for " +  className + "." + method.getName());
 
117
            }
 
118
        }
 
119
    }
 
120
 
 
121
    private static boolean hasOverride(final MethodDeclaration method) {
 
122
        for (final Object modifier : method.modifiers()) {
 
123
            if (modifier instanceof MarkerAnnotation) {
 
124
                final String name = ((MarkerAnnotation) modifier).getTypeName().getFullyQualifiedName();
 
125
                if (name.equals("Override") || name.equals("java.lang.Override")) {
 
126
                    return true;
 
127
                }
 
128
            }
 
129
        }
 
130
        return false;
 
131
    }
 
132
 
 
133
    private static String getFullyQualifiedName(final TypeDeclaration type) {
 
134
        String name = type.getName().getFullyQualifiedName();
 
135
        final CompilationUnit root = (CompilationUnit) type.getRoot();
 
136
        for (ASTNode t = type.getParent(); t != root; t = t.getParent()) {
 
137
            name = ((TypeDeclaration) t).getName().getFullyQualifiedName() + '$' + name;
 
138
        }
 
139
 
 
140
        if (root.getPackage() != null) {
 
141
            final String packageName = root.getPackage().getName().getFullyQualifiedName();
 
142
            name = packageName + '.' + name;
 
143
        }
 
144
        return name;
 
145
    }
 
146
 
 
147
    private static boolean shouldOverride(final MethodDeclaration method) throws Exception {
 
148
        final TypeDeclaration type = (TypeDeclaration) method.getParent();
 
149
        final Class< ? > klass = Class.forName(getFullyQualifiedName(type));
 
150
        final Class< ? >[] types = new Class[method.parameters().size()];
 
151
        for (int i = 0; i < types.length; i++) {
 
152
            final SingleVariableDeclaration parameter = (SingleVariableDeclaration) method.parameters().get(i);
 
153
            types[i] = getClassOf(parameter.getType(), method.isVarargs() && i == method.parameters().size() - 1);
 
154
        }
 
155
 
 
156
        // Check we have the method
 
157
        assertNotNull(klass.getDeclaredMethod(method.getName().getFullyQualifiedName(), types));
 
158
 
 
159
        for (Class< ? > c = klass.getSuperclass(); c != null; c = c.getSuperclass()) {
 
160
            try {
 
161
                c.getDeclaredMethod(method.getName().getFullyQualifiedName(), types);
 
162
                return true;
 
163
            }
 
164
            catch (final NoSuchMethodException e) {
 
165
                //ignore
 
166
            }
 
167
        }
 
168
        return false;
 
169
    }
 
170
 
 
171
    private static Class< ? > getClassOf(final Type type, final boolean isVararg) {
 
172
        Class< ? > klass = null;
 
173
        String name = null;
 
174
        if (isVararg) {
 
175
            if (type instanceof SimpleType) {
 
176
                final Class< ? > elemntClass = getClassOf(type, false);
 
177
                klass = getArrayClassOf(elemntClass.getName(), 1, false);
 
178
            }
 
179
            else if (type instanceof PrimitiveType) {
 
180
                klass = getPrimitiveArrayType(type.toString(), 1);
 
181
            }
 
182
        }
 
183
        else if (type instanceof SimpleType) {
 
184
            name = ((SimpleType) type).getName().getFullyQualifiedName();
 
185
        }
 
186
        else if (type instanceof PrimitiveType) {
 
187
            //TODO: "char x[]" and not "char[] x" comes as Primitive type, this should be handled.
 
188
            name = ((PrimitiveType) type).getPrimitiveTypeCode().toString();
 
189
            klass = getPrimitiveType(name);
 
190
        }
 
191
        else if (type instanceof ArrayType) {
 
192
            final ArrayType arrayType = (ArrayType) type;
 
193
            final Type elementType = arrayType.getElementType();
 
194
            if (elementType instanceof SimpleType) {
 
195
                final Class< ? > elemntClass = getClassOf(elementType, false);
 
196
                klass = getArrayClassOf(elemntClass.getName(), arrayType.getDimensions(), false);
 
197
            }
 
198
            else if (elementType instanceof PrimitiveType) {
 
199
                klass = getPrimitiveArrayType(elementType.toString(), arrayType.getDimensions());
 
200
            }
 
201
            else {
 
202
                throw new IllegalStateException("Can not process type of " + type.getClass().getName());
 
203
            }
 
204
        }
 
205
        else if (type instanceof ParameterizedType) {
 
206
            klass = getClassOf(((ParameterizedType) type).getType(), isVararg);
 
207
        }
 
208
        else {
 
209
            throw new IllegalStateException("Can not process type of " + type.getClass().getName());
 
210
        }
 
211
        if (klass == null) {
 
212
            klass = tryClassName(name);
 
213
        }
 
214
        final CompilationUnit cu = (CompilationUnit) type.getRoot();
 
215
        if (klass == null && cu.getPackage() != null) {
 
216
            klass = tryClassName(cu.getPackage().getName().getFullyQualifiedName() + '.' + name);
 
217
        }
 
218
        if (klass == null) {
 
219
            for (final Object t : cu.types()) {
 
220
                klass = searchClassInAllTypes((TypeDeclaration) t, name);
 
221
                if (klass != null) {
 
222
                    break;
 
223
                }
 
224
            }
 
225
        }
 
226
        if (klass == null) {
 
227
            klass = tryClassName("java.lang." + name);
 
228
        }
 
229
        if (klass == null) {
 
230
        outer:
 
231
            for (final Object i : cu.imports()) {
 
232
                String imported = ((ImportDeclaration) i).toString().trim().substring(7);
 
233
                imported = imported.substring(0, imported.length() - 1);
 
234
                if (imported.endsWith('.' + name)) {
 
235
                    klass = tryClassName(imported);
 
236
                    if (klass != null) {
 
237
                        break;
 
238
                    }
 
239
                    final int period = imported.lastIndexOf('.');
 
240
                    while (period != -1) {
 
241
                        imported = imported.substring(0, period) + '$' + imported.substring(period + 1);
 
242
                        klass = tryClassName(imported);
 
243
                        if (klass != null) {
 
244
                            break outer;
 
245
                        }
 
246
                    }
 
247
                }
 
248
                else if (imported.endsWith(".*;")) {
 
249
                    //TODO: we need to check for any inner class (which needs '$' instead of '.')
 
250
                    klass = tryClassName(imported.substring(0, imported.length() - 1) + name);
 
251
                    if (klass != null) {
 
252
                        break;
 
253
                    }
 
254
                }
 
255
            }
 
256
        }
 
257
        if (klass == null) {
 
258
            throw new IllegalStateException("Can not get class of " +  type);
 
259
        }
 
260
        return klass;
 
261
    }
 
262
 
 
263
    private static Class< ? > tryClassName(final String className) {
 
264
        try {
 
265
            return Class.forName(className);
 
266
        }
 
267
        catch (final Throwable t) {
 
268
            return null;
 
269
        }
 
270
    }
 
271
 
 
272
    private static Class< ? > searchClassInAllTypes(final TypeDeclaration typeDeclaration, final String name) {
 
273
        Class< ? > klass = tryClassName(getFullyQualifiedName(typeDeclaration) + '$' + name);
 
274
        if (klass != null) {
 
275
            return klass;
 
276
        }
 
277
        for (final Object type : typeDeclaration.getTypes()) {
 
278
            klass = searchClassInAllTypes((TypeDeclaration) type, name);
 
279
            if (klass != null) {
 
280
                return klass;
 
281
            }
 
282
        }
 
283
        return null;
 
284
    }
 
285
 
 
286
    private static Class< ? > getPrimitiveArrayType(final String name, final int dimensions) {
 
287
        final String className;
 
288
        if (name.equals("byte")) {
 
289
            className = "B";
 
290
        }
 
291
        else if (name.equals("short")) {
 
292
            className = "S";
 
293
        }
 
294
        else if (name.equals("int")) {
 
295
            className = "I";
 
296
        }
 
297
        else if (name.equals("long")) {
 
298
            className = "J";
 
299
        }
 
300
        else if (name.equals("char")) {
 
301
            className = "C";
 
302
        }
 
303
        else if (name.equals("float")) {
 
304
            className = "F";
 
305
        }
 
306
        else if (name.equals("double")) {
 
307
            className = "D";
 
308
        }
 
309
        else if (name.equals("boolean")) {
 
310
            className = "Z";
 
311
        }
 
312
        else {
 
313
            throw new IllegalArgumentException("Invalid primitive type " + name);
 
314
        }
 
315
 
 
316
        return getArrayClassOf(className, dimensions, true);
 
317
    }
 
318
 
 
319
    private static Class< ? > getArrayClassOf(final String className, final int dimensions, final boolean primitive) {
 
320
        final StringBuilder builder = new StringBuilder();
 
321
        for (int i = 0; i < dimensions; i++) {
 
322
            builder.append('[');
 
323
        }
 
324
        if (!primitive) {
 
325
            builder.append('L');
 
326
        }
 
327
        builder.append(className);
 
328
        if (!primitive) {
 
329
            builder.append(';');
 
330
        }
 
331
        return tryClassName(builder.toString());
 
332
    }
 
333
 
 
334
    private static Class< ? > getPrimitiveType(final String name) {
 
335
        if (name.equals("byte")) {
 
336
            return byte.class;
 
337
        }
 
338
        if (name.equals("short")) {
 
339
            return short.class;
 
340
        }
 
341
        if (name.equals("int")) {
 
342
            return int.class;
 
343
        }
 
344
        if (name.equals("long")) {
 
345
            return long.class;
 
346
        }
 
347
        if (name.equals("char")) {
 
348
            return char.class;
 
349
        }
 
350
        if (name.equals("float")) {
 
351
            return float.class;
 
352
        }
 
353
        if (name.equals("double")) {
 
354
            return double.class;
 
355
        }
 
356
        if (name.equals("boolean")) {
 
357
            return boolean.class;
 
358
        }
 
359
        if (name.equals("void")) {
 
360
            return void.class;
 
361
        }
 
362
        return null;
 
363
    }
 
364
 
 
365
    */
 
366
}