Warn when certain constructor is used
Maurizio Cimadamore
maurizio.cimadamore at oracle.com
Fri Jun 1 11:25:29 UTC 2018
Another option would be to heavily borrow on some frameworks we already
have - e.g. the coding rule one we use for testing quality of langtools
code:
http://hg.openjdk.java.net/jdk/jdk/file/1d5694c1aa03/test/langtools/tools/all/RunCodingRules.java
This runs a series of analyzers, defined here:
http://hg.openjdk.java.net/jdk/jdk/file/1d5694c1aa03/make/langtools/tools/crules
Of these various analyzers, one looks quite similar to what you want:
http://hg.openjdk.java.net/jdk/jdk/file/1d5694c1aa03/make/langtools/tools/crules/AssertCheckAnalyzer.java
The only difference is that it looks for the symbol associated with a
method call, rather than that associated with a new class tree.
So, my suggestion is, maybe you can start by pulling in all that code
into a project and then gradually chop it down until it just do whatever
it is you need?
Regarding javac-specific documentation, you can find some info here:
http://openjdk.java.net/groups/compiler/
(see links at the bottom)
Hope this helps.
Maurizio
On 01/06/18 09:29, Pietro Paolini wrote:
>> (4)
>> obtain the TreePath for the node (by passing compilation unit and tree),
>> and then (5) you call getElement on that path.
> I am probably getting lost here,
>
> @Override
> public Object visitNewClass(NewClassTree newClassTree, Object o) {
>
> TreePath treePath = trees.getPath(compilationUnitTree, newClassTree);
>
> ....
> }
>
> The TreePath class does provide a getElement() method. From the element somehow I could get to the symbol signature which is exactly what I need, I don't quite know how though.
>
> Would you recommend any good source of reliable information on how the compiler organizes the AST and what are the key data structures involved ? I find myself asking you basically everything as - even though I have some familiarity with compiler concepts such as AST, reduce, grammar etc etc - I have a poor knowledge on the javac specific aspects.
>
>
>
>> -----Original Message-----
>> From: Maurizio Cimadamore [mailto:maurizio.cimadamore at oracle.com]
>> Sent: 01 June 2018 00:02
>> To: Pietro Paolini
>> Cc: compiler-dev at openjdk.java.net
>> Subject: Re: Warn when certain constructor is used
>>
>> You can get a treepath from an element here:
>>
>> https://docs.oracle.com/javase/7/docs/jdk/api/javac/tree/com/sun/source/ut
>> il/Trees.html#getPath(javax.lang.model.element.Element)
>>
>> And from the TreePath you obtain there, you can get a compilation unit:
>>
>> https://docs.oracle.com/javase/7/docs/jdk/api/javac/tree/com/sun/source/ut
>> il/TreePath.html#getCompilationUnit()
>>
>> Once you have this ingredient, you can finally obtain a path for any
>> tree you'd like:
>>
>> https://docs.oracle.com/javase/7/docs/jdk/api/javac/tree/com/sun/source/ut
>> il/Trees.html#getPath(com.sun.source.tree.CompilationUnitTree,%20com.sun.
>> source.tree.Tree)
>>
>>
>> So, I suggest you (1) obtain the TreePath form one of your root elements
>> (2) extract the compilation unit from one of these path and stash it
>> somewhere (3) when you reach the node you want (visitNewClass), you (4)
>> obtain the TreePath for the node (by passing compilation unit and tree),
>> and then (5) you call getElement on that path.
>>
>> Maurizio
>>
>> On 31/05/18 22:25, Pietro Paolini wrote:
>> https://docs.oracle.com/javase/7/docs/jdk/api/javac/tree/com/sun/source/ut
>>>> il/Trees.html#getElement(com.sun.source.util.TreePath)
>>> On what kind of object ?
>>>
>>> if (!roundEnv.processingOver()) {
>>> Set<? extends Element> elements = roundEnv.getRootElements();
>>> for (Element element : elements) {
>>> if (element.getKind() == ElementKind.CLASS) {
>>> JCTree tree = (JCTree) trees.getTree(element).accept(new
>> LocalDateUtilDate(), null);
>>> }
>>>
>>> System.out.println(element);
>>> }
>>> }
>>>
>>> I haven't met any "TreePath" as yet.
>>>
>>>> -----Original Message-----
>>>> From: Maurizio Cimadamore [mailto:maurizio.cimadamore at oracle.com]
>>>> Sent: 31 May 2018 15:45
>>>> To: Pietro Paolini
>>>> Cc: compiler-dev at openjdk.java.net
>>>> Subject: Re: Warn when certain constructor is used
>>>>
>>>> Try to call
>>>>
>>>>
>> https://docs.oracle.com/javase/7/docs/jdk/api/javac/tree/com/sun/source/ut
>>>> il/Trees.html#getElement(com.sun.source.util.TreePath)
>>>>
>>>> This should trigger attribution of the tree and give you the 'symbol'
>>>> associated with the constructor. From there you can access the symbol
>>>> signature using
>>>>
>>>>
>> https://docs.oracle.com/javase/7/docs/api/javax/lang/model/element/Eleme
>>>> nt.html#asType()
>>>>
>>>> And downcasting to this:
>>>>
>>>>
>> https://docs.oracle.com/javase/7/docs/api/javax/lang/model/type/Executable
>>>> Type.html
>>>>
>>>> If this works, good, otherwise the solution would be more cumbersome -
>>>> and it will involve setting up a task listener. But try this first.
>>>>
>>>> Maurizio
>>>>
>>>>
>>>> On 31/05/18 13:19, Pietro Paolini wrote:
>>>>> Hi Maurizio,
>>>>>
>>>>> Thanks a lot. I would have an additional, and hopefully last, question.
>>>>>
>>>>> I am getting the NewClassTree which seems to provide me access to the -
>>>> forgive me the coarse wording of it - the "token", namely the textual
>>>> representation
>>>>> of it, while I am mainly interested in the type.
>>>>>
>>>>> I am getting around it by comparing strings but I wonder if there is any
>> way
>>>> to get to the type of the expression :
>>>>> := new identifier ( arguments )
>>>>>
>>>>> What I have in my mind is to detect all instances in which the identifier
>> has
>>>> *type* A and the argument's list is composed by a single *type* , let say B.
>>>> That allows me to
>>>>> print something:
>>>>>
>>>>> "Hey, constructor new A(B) has been detected"
>>>>>
>>>>> Thanks a lot for your help so far, really.
>>>>>
>>>>> Thanks,
>>>>> P.
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>> -----Original Message-----
>>>>>> From: Maurizio Cimadamore [mailto:maurizio.cimadamore at oracle.com]
>>>>>> Sent: 31 May 2018 12:45
>>>>>> To: Pietro Paolini
>>>>>> Cc: compiler-dev at openjdk.java.net
>>>>>> Subject: Re: Warn when certain constructor is used
>>>>>>
>>>>>>
>>>>>>
>>>>>> On 31/05/18 12:21, Pietro Paolini wrote:
>>>>>>> JCTree tree = (JCTree) trees.getTree(element);
>>>>>>> tree.accept(new LocalDateUtilDate());
>>>>>> There re two visitor methods in JCTree, one internal (used by javac),
>>>>>> one external (used by the API). I don't think you need to cast down to
>>>>>> JCTree (yet, at least). Just keep it as a com.sun.source.tree.Tree, and
>>>>>> you will see that the only 'accept' method there takes two arguments: a
>>>>>> visitor (which you have) and a visitor parameter; since you don't seem
>>>>>> to need a visitor parameter, you can just pass 'null' as second
>> parameter.
>>>>>> Maurizio
More information about the compiler-dev
mailing list