Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix JavadocTool import for Java9 and up #2853

Merged
merged 10 commits into from Nov 9, 2018

Conversation

ghost
Copy link

@ghost ghost commented Jun 5, 2018

JavadocTool, Messager and ModifierFilter is moved to a different package since Jigsaw.

Checked with

  • openjdk version "10.0.1" 2018-04-17
    OpenJDK Runtime Environment (build 10.0.1+10-Ubuntu-3ubuntu1)
  • java version "9.0.4"
    Java(TM) SE Runtime Environment (build 9.0.4+11)
  • java version "1.8.0_171"
    Java(TM) SE Runtime Environment (build 9.0.4+11)

@pekkaklarck
Copy link
Member

Thanks for the PR! Could you also submit an issue about this so that we get it listed in the release notes?

@pekkaklarck pekkaklarck closed this Jun 5, 2018
@pekkaklarck pekkaklarck reopened this Jun 5, 2018
@pekkaklarck
Copy link
Member

Didn't mean to close this. Having "Close and comment" and "Comment" buttons next to each others is annoying...

@ghost
Copy link
Author

ghost commented Jun 5, 2018

Sure thing #2854

PS I am about to do a PR on the maven plugin too, for the same reasons.

@pekkaklarck
Copy link
Member

Hopefully we could get @jussimalinen to fix the problem in Mavan plugin and create a new release. I'll ping him on Slack as well.

@pekkaklarck
Copy link
Member

I've been trying to test this locally but haven't really succeeded. What I've done:

  • Install Java 10 (Java 9 seems to be EOL) and then Jython 2.7.0 using it. No problems here.
  • Test the aforementioned combo with while having tools.jar from Java 8 in CLASSPATH without making any changes. Worked just fine.
  • Tried to find tools.jar for Java 10 specially but apparently it's not anymore included in Java 9 or newer.

How did you @Aquator test this? Is there a replacement for tools.jar when using Java 9+?

@ghost
Copy link
Author

ghost commented Jun 5, 2018

Nope, it have been removed.

Classes from it are moved to new modules, the Javadoc part is in the jdk.javadoc module, that is on the classpath by default, but it is not opened for others to access.

JDK9 should give you a warning about that, but allow anyway, but later versions will fail. That is the trick I do in robotframework/MavenPlugin@99108b2 with the
--add-opens jdk.javadoc/com.sun.tools.javadoc.main=ALL-UNNAMED argument - that tells java that the package of that module is open for all other modules.

So with Java10 you probably also need to provide this argument, otherwise it will fail. I confess I had troubles running the tests, as invoke needed Python3 to create the jar, but tests used 2.7, and it ended up in a mess - so eventually tested the jar with the maven plugin.

@pekkaklarck
Copy link
Member

Do I get it right that with Java 10 you don't need tools.jar anymore (and it's not part of the distribution either) but then you need to use --add-opens jdk.javadoc/com.sun.tools.javadoc.main=ALL-UNNAMED and also change the imports as described in this PR? If that's the case, then we definitely should also document this in Libdoc's documentation. Or is the some way we could programmatically enable that automatically?

I haven't yet tested the aforementioned option, but based on my tests Libdoc works with Java 10 if using tools.jar. It's not too convenient if you don't have tools.jar otherwise because it's not part of the distribution. This might be something to take into account with this PR, though, because the proposed change would break using tools.jar with Java 10. Perhaps it should be changed so that the current import is tried first and then another import is used if it fails.

It's true that at one point building RF (including the jar distribution) required Python 3.6 but running tests required Python 2.7. Luckily nowadays it's Python 3.6 (or newer) everywhere.

@ghost
Copy link
Author

ghost commented Jun 5, 2018 via email

@pekkaklarck
Copy link
Member

Using non-deprecated APIs would obviously be a lot better. It would be great if you could take a look at that.

Because using tools.jar is the only way to create docs nowadays, and it also works with Java 10, we should avoid breaking that. If generating docs requires strange command line options to be passed via Jython to Java, that needs to be separately documented.

@ghost
Copy link
Author

ghost commented Jun 6, 2018

Okay, give me a few hours, I'll look into it. I'll also try to run the tests with Python2 this time :)

@ghost
Copy link
Author

ghost commented Jun 6, 2018

It is heavily modified in 9 but I’ll try to come up with something this week. ClassDoc is deprecated too, I am trying to gather the same data with the new API. Of course no straightforward migration docs available :)

@ghost
Copy link
Author

ghost commented Jun 7, 2018

Well, here is the thing: I think it can not be done with Jython at the moment. I can access the new ToolProvider and get a DocumentationTool instance, but if I want to go further and invoke anything on the doctool instance, the Jython will try to use reflection on jdk.javadoc.internal.api.JavadocTool - an implementation of the DocumentationTool. That will fail of course, since that class is not exported.

Considering this, I think the best way we can make it work is your suggestion on importing order, and on jdk10 the --add-opens must be set in the running side, when invoking java.

Unless of course there is a way to convince Jython not to access the direct type when calling the function.

Could not stand it to use Jython's reflection to call Java's reflection ;) All hope is not lost just yet.

@ghost
Copy link
Author

ghost commented Jun 8, 2018

Okay, I think I got this. Some more typing is needed to cover the constructor, method and parameter parts, but in general it is working. Hopefully I can update the PR with the changes early next week, and you can review things.

@ghost
Copy link
Author

ghost commented Jun 11, 2018

This is another attempt. Please pardon my Python.... The base idea is to hide all the changes from libdoc. It might be a better idea to pull that stuff out to it's own file, I wanted to keep impact on minimum.

Did some smoke tests, but an excessive feature test of the docs should be run - not sure how deeply atest tests this.

I have 39 test failures with atest/run.py /usr/bin/python --exclude no-ci atest/robot - but I have the same results for Java8, Java9 and Java10.

Can you review the changes? This should be more future-proof, and no need to tinkle with command line args.

@ghost
Copy link
Author

ghost commented Jun 18, 2018

Heya, @pekkaklarck can you give a heads-up when you think you'll have time to look at it? - no rush, just preparing for summer holiday season :D

@pekkaklarck
Copy link
Member

I hopefully have time to look at this later today. Summer holiday season, most importantly kids who are not in school or kindergarten, is somewhat reducing my effectiveness....

@ghost
Copy link
Author

ghost commented Jun 19, 2018

Haha, I get you, we still have a couple of extra kindergarden days before all hell's loose. Thanks for making time for it.

@pekkaklarck
Copy link
Member

Finally got time to really look at this. You must have done a lot of digging to find replacements for JavaDoc tool. Luckily the code doesn't look too complicated, and I got few ideas how it possibly could be improved.

A problem with the PR is that when I try to run Libdoc acceptance tests using Java 10 with these changes, plenty of tests related to handling Java based libraries fail. How have you tested the changes? Did you try running the existing acceptance tests? If you haven't looked at the acceptance tests earlier, you can find more information about them in atest/README.rst file.

The command I used was

atest/run.py jython atest/robot/libdoc/java_library.robot

and this is the output I got:

Running suite 'Java Library' with 19 tests.
====================================================================================================
.........FFFFFFFFFF
----------------------------------------------------------------------------------------------------
FAIL: Java Library.Keyword Names
Clone != Keyword
----------------------------------------------------------------------------------------------------
FAIL: Java Library.Keyword Arguments
[] != ['arg']
----------------------------------------------------------------------------------------------------
FAIL: Java Library.Keyword Documentation
'' does not match 'Takes one `arg` and *does nothing* with it.

Example:
| Your Keyword | xxx |
| Your Keyword | yyy |

See `My Keyword` for no more information.*'
----------------------------------------------------------------------------------------------------
FAIL: Java Library.Non ASCII
Takes one `arg` and *does nothing* with it.

Example:
| Your Keyword | xxx |
| Your Keyword | yyy |

See `My Keyword` for no more information. != Hyvää yötä.

Спасибо!
----------------------------------------------------------------------------------------------------
FAIL: Java Library.Lists as varargs
['arg0', 'arg1'] != ['*varargsList']
----------------------------------------------------------------------------------------------------
FAIL: Java Library.Kwargs
['arg0'] != ['normal', '*varargs', '**kwargs']
----------------------------------------------------------------------------------------------------
FAIL: Java Library.Only last map is kwargs
[] != ['normal', '**kwargs']
----------------------------------------------------------------------------------------------------
FAIL: Java Library.Only last list is varargs
['arg0'] != ['normalArray', '*varargs']
----------------------------------------------------------------------------------------------------
FAIL: Java Library.Last argument overrides
[] != ['normalArray', 'normalMap', 'normal']
----------------------------------------------------------------------------------------------------
FAIL: Java Library.Keyword tags
[] != ['bar', 'foo']
====================================================================================================
Run suite 'Java Library' with 19 tests in 5 seconds 813 milliseconds.

FAILED
19 critical tests, 9 passed, 10 failed
19 tests total, 9 passed, 10 failed

@ghost
Copy link
Author

ghost commented Jun 21, 2018

Thanks, I'll dig into those specific tests. I've run the tests, but I have some failures no matter what, even with Java8. I hoped it is something on my machine, locale or other badly configured Python thingie. But I can definitely check out these tomorrow.

@ghost
Copy link
Author

ghost commented Jun 22, 2018

Okay, I was careless with varargs, used typeMirror.getKind instead of typeMirror.getKind() Hmmpf.
Others were due to too many methods added, now I am filtering the methods declared in the class, before all the public methods in the class hierarchy were added.

atest/run.py jython atest/robot/libdoc/java_library.robot passed for me for JDK9 and JDK10, and for some reasons I can't run it in (open)JDK8. It looks like a Jython issue to me regarding file paths, It can't copy the test file to /tmp/robottests.

@ghost
Copy link
Author

ghost commented Jul 9, 2018

@pekkaklarck can you take a look at it this week? Then I'll be off for the rest of the month.

@ghost
Copy link
Author

ghost commented Sep 5, 2018

@pekkaklarck hey, it is just a gentle ping on this after holiday season ;)

@pekkaklarck
Copy link
Member

Sorry, haven't had time to look at this due to concentrating on implementing automatic type conversion. Once that's done, hopefully soon, I plan to the long overdue create 3.1 alpha 2 release and after that look at this and the other open pull requests.

@ghost
Copy link
Author

ghost commented Oct 17, 2018

Hey @pekkaklarck this is another gentle poke. We are going java11 this month, and all my advocated robot tests will spin in mayhem (could hack with arguments for java9 but those times are over now). Is there any chance this will be pulled in, like soon, or should I roll my own versions of robot and maven plugin for the time being?

@cristiadu
Copy link

Same question as @Aquator , I'm also blocked from moving our test project to java 10 due to this tools.jar issue. (My problem is on the MavenPlugin actually, as I cannot remove the dependency myself the same way I did with the other libs that were doing the same import).

@pekkaklarck
Copy link
Member

pekkaklarck commented Oct 25, 2018

Finally time to look at this. The code for getting the information via javax.tools.DocumentationTool looks somewhat complicated, but we cannot really improve JDK APIs. We just need to get the information we need and preferably get it via a stable API.

Constructing ClassDocLike based on the information we get doesn't feel like a good idea when in the end we just want to construct Libdoc's LibraryDoc instance. Wouldn't it be easier to have a separate builder that directly uses the info we get via javax.tools and constructs LibradyDoc instances based on that? It could reside in a separate module like javaxbuilder.py or java9builder.py and builder.py changed to contain something like this:

if JYTHON:
    if JAVA_VERSION < '1.9':
        from .javabuilder import JavaDocBuilder
    else:
        from .java9builder import JavaDocBuilder
else:
    def JavaDocBuilder():
        raise DataError('Documenting Java test libraries requires Jython.')

If the javax.tools approach works also with Java 8, could consider using it also with it, though. Could then consider renaming the old javabuilder to oldjavabuilder and the new to javabuilder

@ghost
Copy link
Author

ghost commented Oct 25, 2018 via email

@pekkaklarck
Copy link
Member

pekkaklarck commented Oct 26, 2018

That sounds good @Aquator. Except for that virus bingo. Hoping swift recovery!

I try to get RF 3.1 beta 1 released today, them I'm on holiday next week, and aim for beta 2 (or rc 1) the week after. It would be great if you had time to look at this before that.

@ghost
Copy link
Author

ghost commented Nov 7, 2018

@pekkaklarck did some refactoring, it indeed became smaller and better separated. Tested with Java7, Java8, Java10, Java11, all test passing (atest/run.py jython atest/robot/libdoc/java_library.robot)

Since it is hard to have all these javas with jython and remain sane, I created some docker images, let me know if you'd like to have them for testing. (Based on OpenJDK) - there are no traces of Java9 left, so I did not test on that version.

Hope I am still in time for release ;)

@pekkaklarck
Copy link
Member

Looking at the latest changes now. First thing I noticed was that sys.platform[4:7] doesn't really work anymore with Java 10 when sys.platform is in format like java10.0.2 and not like java1.8.0_191. Because also old code used this approach, decided to introduce new JAVA_VERSION constant that stores the version as a tuple of integers. That was done in 3edb53c.

@ghost
Copy link
Author

ghost commented Nov 8, 2018

Fair enough, using the new method now. Did an update on my branch from master, hope it's not a problem.

@pekkaklarck
Copy link
Member

Tested this locally and code seems to work pretty well. Noticed one test failing due to private constructors not being ignored. The failing test is Libdoc.No Inits.Java Class With Default and Private Constructors.

After a bit more investigation noticed that private keywords aren't ignored either. The reason no test failed was that we didn't have any test for private Java keywords with Libdoc! Added two explicit tests in 1645e9d.

@ghost
Copy link
Author

ghost commented Nov 8, 2018

I've added the filtering for constructors and methods, and moved the field filtering to the same place from the _get_attr so now only public things are returned in the first place.

@pekkaklarck
Copy link
Member

I would assume that fixing the aforementioned problem with private keywords and constructors isn't too complicated. After that all functionality ought to be there, but there are two more things to do:

  1. Update documentation in the User Guide. Need to explain that starting from RF 3.1 documenting Java libraries works out-of-the-box with Java 9+ but with earlier you need to have tools.jar in CLASSPATH. Shouldn't be a big task and I can do this if you don't want to spend time learning how to update the User Guide.

  2. Code cleanup. There are some PEP-8 violations and other things I'd like to get cleaned up. I could go through the code line-by-line and add comments where applicable, but that would be quite slow. Could you instead (re-)read PEP-8 and go the code through once more yourself? I can then add comments about the possible remaining issues or fix them myself.

@ghost
Copy link
Author

ghost commented Nov 8, 2018

I'll look into PEP-8, but I'd be happy to pass the documentation part. Is that okay to push the PEP-8 tomorrow?

@pekkaklarck
Copy link
Member

Confirmed locally that all Libdoc tests now pass with Java 10. Great work!

@pekkaklarck
Copy link
Member

OK, I'll take care of the documentation updates after this PR is merged. Code cleanup waiting until tomorrow is fine. I need to leave now anyway and may actually not have time for coding/reviews tomorrow either. I'm at the Agile Testing Days conference next week but ought to have time for reviews at some point. More actively coding the week after and trying to get RC 1 out then as well.

@ghost
Copy link
Author

ghost commented Nov 8, 2018

Was not too many, so fixed those too, at least I hope

@pekkaklarck
Copy link
Member

Looks a lot better! I'll add some more detailed comments later today or tomorrow.

Copy link
Member

@pekkaklarck pekkaklarck left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As discussed earlier, the code ought to work fine already. These comments are thus mainly about style and some of them are somewhat nitpickey. Please take a look and change those you think are worth changing. Feel free to ask for details here or on Slack if some of the comments aren't clear.

src/robot/libdocpkg/java9builder.py Outdated Show resolved Hide resolved
if doc_comment is None:
return ''
else:
return '\n'.join(line.strip() for line in doc_comment.splitlines())
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this code needed to cleanup indentation? If yes, it might be possible to use use inspect.cleandoc here instead. Could then also be used by the old tools.jar code.

Some nitpickey comments about the style:

  1. It is considered a bit more pythonic to use if not doc_comment, not if doc_comment is None in cases like this. Personally I'd avoid the whole thing with something like doc = elements.getDocComment(element) or ''.

  2. As a personal preference, I tend to omit else branches when they aren't needed. Here the if branch returns so else is unnecessary. Obviously the whole if/else is removed if possible None is handled with or ''.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cleandoc makes things different here with leading whitespaces (they are removed only when they are uniform in all lines) that results in a failing test, but agree with the other parts

src/robot/libdocpkg/java9builder.py Outdated Show resolved Hide resolved
src/robot/libdocpkg/java9builder.py Outdated Show resolved Hide resolved
src/robot/libdocpkg/java9builder.py Outdated Show resolved Hide resolved
src/robot/libdocpkg/java9builder.py Outdated Show resolved Hide resolved
src/robot/libdocpkg/java9builder.py Outdated Show resolved Hide resolved
src/robot/libdocpkg/java9builder.py Outdated Show resolved Hide resolved
src/robot/libdocpkg/java9builder.py Outdated Show resolved Hide resolved
@ghost
Copy link
Author

ghost commented Nov 9, 2018

Apart from cleandoc I've basically pulled in all your suggestions, and tried to kick it in shape. Should be PEP-8 too.

@pekkaklarck
Copy link
Member

I would actually say cleandoc works fine and the test is wrong. The same issue is in the old code so both should be changed at the same time. I can do that.

@pekkaklarck pekkaklarck merged commit 2893a65 into robotframework:master Nov 9, 2018
@pekkaklarck
Copy link
Member

Didn't find anything worth changing and merged this PR. Thanks for your hard work deciphering how to use the related Java APIs @Aquator!

I'll update docs and consider taking cleandoc into use. I'm also thinking should the modules be renamed but not sure what would be better names...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants