Review request for type annotation reflection test
Sergey Grinev
sergey.grinev at oracle.com
Fri Aug 23 06:52:16 PDT 2013
Also few minor comments:
1. Helper#getAnno()
StringBuffer result = new StringBuffer("");
using StringBuilder is recommended for thread-safe methods
2. List Helper.getMultipleAT()
this method uses List where List<String> can be specified
3. Helper.compareAnnoWithDiffSeq()
this can be done much shorted and without copying array to list:
String[] split1 = anno1.trim().split("\\s+");
String[] split2 = anno2.trim().split("\\s+");
Arrays.sort(split1);
Arrays.sort(split2);
return Arrays.equals(split1, split2);
4. Helper.compileCode():697-704 can be simplified using jdk8 streams:
ok = diagnostics.getDiagnostics().stream().anyMatch(d -> d.getKind() == Diagnostic.Kind.ERROR);
5. Same for Helper.isPkgInfoPresent:
return files.stream().map(JavaFileObject::getName).anyMatch(name -> name.contains("package-info") || name.contains("PkgAnno"));
6. AnnotatedArrayTypeGetAnnotatedGenericComponentTypeTest:175
You are calling Helper.getArrAT(at) then split it by ";" and work with
result.
while Helper.getArrAT() takes a list and convert it into string:
return getAnno(annotations) + ";" + ret;
It may be more efficient to work directly with lists.
7. DeclarationGenerator interface is never used as interface
8. Helper.Declaration.replaceAnnoStr should be static
9. Helper.Declaration.replaceAnnoStr/getFirstAnno return result as
String[] array, which is considered to be a bad practice (you are using
variable length structure to store exactly 2 values). It would be
cleaner to introduce intermediate structure of 2 string to store return
value.
-- Sergey
On 23-Aug-13 14:36, Sergey Grinev wrote:
> Hi, all.
>
> Sorry if this review covers same issue I reported on reviewboard one,
> but it seems few important point were not fixed:
>
> 1. public Map<Helper.Declaration, Object> lhm = new LinkedHashMap<>();
> and
> public synchronized static String genDeclaration(
> Map<Helper.Declaration, Object> input, Declaration...
> srcType)
>
> - fields used as a method-local temporary variables are error-prone
> and confusing. Users/readers of that code are not aware when this
> field can be used or when this field can be cleared, also using such
> field is not thread-safe. Imagine someone added one more ENUM value to
> TestCase, used lhm and didn't call lhm.clear() -- things will break
> and very different place this person didn't even touch.
>
> - Map claims it stores Objects but actually they are only String and
> String[]. Thus your getDeclaration() has invalid signature and is
> error-prone. Also you calls instanceof several times to resolve this
> ambiguity which is considered to be an anti-pattern as well.
>
> You can solve these problems by introducing separate entity
> responsible for declaration generation:
>
> public class DeclarationGenerator {
>
> private final Map<Helper.Declaration, String[]> lhm = new
> LinkedHashMap<>();
> public void add(Helper.Declaration key, String... value) {
> lhm.put(key, value);
> }
> public String genDeclaration(Declaration... srcType) {
> //...
> for (Declaration st : Declaration.values()) {
> if (input.containsKey(st))
> result.append(st.getSrc(input.get(st)));
> }
> //...
> }
> }
>
> with this helper class instead of
>
> lhm.clear();
> lhm.put(Helper.Declaration.IMPORT, null);
> lhm.put(Helper.Declaration.CLASS, str[0]);
> testCode += Helper.genDeclaration(lhm);
>
> you can write
>
> DeclarationGenerator dg = new DeclarationGenerator();
> // not to reuse, create new one for each generation
> dg.put(Helper.Declaration.IMPORT, null);
> dg.put(Helper.Declaration.CLASS, str[0]);
> testCode += dg.genDeclaration();
>
> having clean design without field used as temporary variable and type
> ambiguity.
>
>
> 2. several TestCase enum entries, especially TESTBASECLSSTART and
> TESTBASECLS are copypasted in several places.
>
> 3. public static Map<String, String> testInput = new LinkedHashMap<>();
>
> why this field in static?
>
>
> -- Sergey
>
> On 22-Aug-13 22:43, Alex Buckley wrote:
>> I have no further comments. Thanks for all your work to test this new
>> and expansive API.
>>
>> Alex
>>
>> On 8/20/2013 1:56 AM, Charlie Wang wrote:
>>> Hi Alex,
>>> I used testInput.size() instead of static int clsIdx as suffix this
>>> time. And other update according to your comments.
>>>
>>> Here's the link. Please review again.
>>> http://cr.openjdk.java.net/~pzhang/Charlie/TypeAnnotation1/webrev/
>>>
>>>
>>> - Charlie
>>>
>>> On 2013/8/9 1:05, Alex Buckley wrote:
>>>> - AnnotationTest.i/clsIdx: it wasn't the name of the variable I was
>>>> objecting to. It was the fact that you're relying on a mutable public
>>>> static variable at all.
>>>>
>>>> - GenTestCode should take Class<? extends TestCaseGenerator>, so you
>>>> don't need to cast to TestCaseGenerator in GenTestCode. (Same comment
>>>> for AnnotationTest.compileCode).
>>>>
>>>> - AnnotationTest.testInput is a Map<Object,String> but I'm sure you
>>>> can do better than Object for keys.'
>>>>
>>>> - ExecutableGetAnnotatedParameterTypesTest.testInput hides
>>>> AnnotationTest.testInput, but swaps the order of the type arguments!
>>>> Map<String,Object> is either wrong, or should not use Object.
>>>>
>>>> Alex
>
More information about the type-annotations-dev
mailing list