Skip to content

Conversation

@gselzer
Copy link
Member

@gselzer gselzer commented Jun 29, 2023

This PR introduces a new SciJava annotation processor to replace the usage of therapi. The processor creates YAML files describing all implementations (identified with an @implNote tag), for use in SciJava 3.

The YAML created by the processor is designed for usage beyond Ops, and for robust declaration of implementations from arbitrary, cross-langauge sources. Each implementation must contain the following:

  • An implementation type. Implementations are binned by their implementation type into type.yaml files (for example, op.yaml contains all of the op implementations discovered by the processor).
  • An implementation source, a URI that some yaml reader could use to get an instance of the implementation. For example, this could be a FQCN in Java, along with a scheme identifying that the URI is a Java class scheme.
  • A map of tags, containing type-specific information. For ops, this includes the op's name, it's parameter information, priority, etc.

As an example, here's an Op:

	/**
	 * A Field Op
	 * @implNote op name=example.mul
	 * @input a the first double
	 * @input b the first double
	 * @output the product
	 */
	public final BiFunction<Double, Double, Double> multiply = (a, b) -> a * b;

And here is the generated YAML, placed into op.yaml:

  - op:
      name: example.mul
      priority: 0.0
      source: javaField:/org.scijava.ops.engine.yaml.ops.YAMLFieldOp$multiply/v0.0
      parameters:
        - input: in1
          description: The first input
        - input: in2
          description: The second input
        - output: out
          description: The product

Although the build completes and passes tests, this PR is a draft as there are a couple things left to do:

  • Polish the annotation processor, and the yaml readers, and the schema we're currently using - while ImageJ Ops2 tests it, I'm sure there are still edge cases and inefficiencies.
  • Determine whether we need @hinerm's ruby script in pom.xml to merge the *.yaml files between source and tests - @ctrueden seemed to think that we don't need to do that. My experience is that it is necessary, though..

@ctrueden
Copy link
Member

What I suggested was to make the path to the YAML for src/test distinct, like op.test.yaml, and check whether the getResources call is able to discover it then. I.e. is the problem a clash between multiple YAML files of the same path in the same project? Or is the issue merely discovery of resources in target/test-classes in general, maybe due to JPMS issues? If the former, using a different name works around the problem.

@gselzer
Copy link
Member Author

gselzer commented Jul 10, 2023

Closes scijava/scijava#65

@gselzer gselzer force-pushed the scijava/scijava-javadoc-parser/javadoc-to-yaml branch from ec94780 to 33a339e Compare July 11, 2023 16:48
@gselzer gselzer marked this pull request as ready for review July 11, 2023 17:01
Copy link
Member

@ctrueden ctrueden left a comment

Choose a reason for hiding this comment

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

Thank you so much for working on this, @gselzer! I'm excited to have ops driven uniformly by YAML metadata. But it looks like this PR is not quite ready for review yet:

  • The description has empty code blocks for the op and corresponding YAML.
  • The commit history has WIPs.

@gselzer gselzer force-pushed the scijava/scijava-javadoc-parser/javadoc-to-yaml branch from 33a339e to 2c67649 Compare July 17, 2023 15:08
@gselzer
Copy link
Member Author

gselzer commented Jul 17, 2023

@ctrueden I edited my PR to add the example Op and resulting YAML, and squashed together all of the WIP commits into a single commit, because things really weren't passing the build until the very end. Should be good to go now!

@hinerm
Copy link
Member

hinerm commented Aug 17, 2023

Build with:
mvn clean install -pl scijava/scijava-javadoc-parser -am; mvn clean install

Questions:

  • Can everything build in on multi-module build? Or does the javadoc parser need to be in its own component?
  • Is there an easier way to debug the annotation processor than logging output?

@hinerm
Copy link
Member

hinerm commented Aug 18, 2023

@gselzer what are the benefits to replacing the therapi mechanism for harvesting Javadoc ops? I didn't see a corresponding issue for this PR.

@gselzer
Copy link
Member Author

gselzer commented Aug 18, 2023

@gselzer what are the benefits to replacing the therapi mechanism for harvesting Javadoc ops? I didn't see a corresponding issue for this PR.

  • Some benefits are described in Improve the shortcomings of therapi javadoc processing scijava#65.
  • A further benefit is that we no longer have to scan the entire classpath. Right now, there is no way to ask therapi "give me all javadoc'd elements that contain an @implNote annotation - we have to scan the entire classpath to do that, which actually breaks down when the classpath isn't fully populated e.g. in Fiji. It's also expensive.

There may be more, which I'm forgetting...

@hinerm hinerm force-pushed the scijava/scijava-javadoc-parser/javadoc-to-yaml branch from 899a953 to 294dc26 Compare August 18, 2023 17:53
@gselzer gselzer linked an issue Aug 23, 2023 that may be closed by this pull request
@hinerm hinerm force-pushed the scijava/scijava-javadoc-parser/javadoc-to-yaml branch from 294dc26 to 95fb6c9 Compare August 24, 2023 14:13
@hinerm
Copy link
Member

hinerm commented Aug 24, 2023

@gselzer I've rebased this branch against main. Currently all the imagej-ops tests are failing, despite running the separate mvn clean install -pl scijava/scijava-javadoc-parser -am; mvn clean install commands. Can you take a look?

Also are the op parameter names being retained? Can you point me to an example of where they are used?

@gselzer
Copy link
Member Author

gselzer commented Aug 28, 2023

@hinerm looking now, it seems to be an issue with type variables. There are some identifiers in the imagej ops2 yaml that have type variables, such as:

net.imagej.ops2.copy.Copiers.<T>copyType(T, T)

unfortunately, we are not correctly reifying the parameter types. I think that the solution is just to erase the type variables to their bounds. I'll let you know when I have a fix.

@gselzer gselzer force-pushed the scijava/scijava-javadoc-parser/javadoc-to-yaml branch from 90f156f to d3fa2a6 Compare August 29, 2023 13:43
@hinerm
Copy link
Member

hinerm commented Aug 29, 2023

@gselzer based on discussion today:

  • Identify where exceptions are being eaten for invalid op javadoc (methods without a type) and see if we can get that to fail compilation

@gselzer gselzer force-pushed the scijava/scijava-javadoc-parser/javadoc-to-yaml branch from d3fa2a6 to 0574e21 Compare August 29, 2023 15:17
@gselzer
Copy link
Member Author

gselzer commented Aug 29, 2023

@gselzer based on discussion today:

* [ ]  Identify where exceptions are being eaten for invalid op javadoc (methods without a type) and see if we can get that to fail compilation

So, looking back at this, I think we should avoid failing compilation - the javadoc parser is designed to be more general than Ops, and thus we may not always want to conform to the Javadoc requirements for an Op.

What we can do is ensure that the tests fail because an Op written as a method doesn't have a type hint. Right now, if we miss a type hint, the errors look like this:

[ERROR] Tests run: 4, Failures: 0, Errors: 4, Skipped: 0, Time elapsed: 0.173 s <<< FAILURE! - in org.scijava.ops.engine.yaml.YAMLOpTest
[ERROR] testYAMLFunction  Time elapsed: 0.075 s  <<< ERROR!
java.lang.IllegalArgumentException: java.lang.RuntimeException: java.lang.RuntimeException: Op org.scijava.ops.engine.yaml.ops.YAMLMethodOp.subtract(java.lang.Double,java.lang.Double) could not be loaded: Could not load class null
	at org.scijava.ops.engine@0-SNAPSHOT/org.scijava.ops.engine.yaml.YAMLOpTest.testYAMLFunction(YAMLOpTest.java:69)
Caused by: java.lang.RuntimeException: java.lang.RuntimeException: Op org.scijava.ops.engine.yaml.ops.YAMLMethodOp.subtract(java.lang.Double,java.lang.Double) could not be loaded: Could not load class null
	at org.scijava.ops.engine@0-SNAPSHOT/org.scijava.ops.engine.yaml.YAMLOpTest.testYAMLFunction(YAMLOpTest.java:69)
Caused by: java.lang.RuntimeException: Op org.scijava.ops.engine.yaml.ops.YAMLMethodOp.subtract(java.lang.Double,java.lang.Double) could not be loaded: Could not load class null
	at org.scijava.ops.engine@0-SNAPSHOT/org.scijava.ops.engine.yaml.YAMLOpTest.testYAMLFunction(YAMLOpTest.java:69)
Caused by: java.lang.NullPointerException: Cannot invoke "String.equals(Object)" because "name" is null
	at org.scijava.ops.engine@0-SNAPSHOT/org.scijava.ops.engine.yaml.YAMLOpTest.testYAMLFunction(YAMLOpTest.java:69)

[ERROR] testYAMLClass  Time elapsed: 0.001 s  <<< ERROR!
org.scijava.ops.api.features.OpMatchingException: No MatchingRoutine was able to produce a match!
	at org.scijava.ops.engine@0-SNAPSHOT/org.scijava.ops.engine.yaml.YAMLOpTest.testYAMLClass(YAMLOpTest.java:48)

[ERROR] testYAMLInnerClass  Time elapsed: 0.001 s  <<< ERROR!
org.scijava.ops.api.features.OpMatchingException: No MatchingRoutine was able to produce a match!
	at org.scijava.ops.engine@0-SNAPSHOT/org.scijava.ops.engine.yaml.YAMLOpTest.testYAMLInnerClass(YAMLOpTest.java:55)

[ERROR] testYAMLMethod  Time elapsed: 0 s  <<< ERROR!
org.scijava.ops.api.features.OpMatchingException: No MatchingRoutine was able to produce a match!
	at org.scijava.ops.engine@0-SNAPSHOT/org.scijava.ops.engine.yaml.YAMLOpTest.testYAMLMethod(YAMLOpTest.java:62)

I think this is good enough, for now.

Copy link
Member Author

@gselzer gselzer left a comment

Choose a reason for hiding this comment

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

Reviewed a little bit!

.github/build.sh Outdated
#!/bin/sh
curl -fsLO https://raw.githubusercontent.com/scijava/scijava-scripts/master/ci-build.sh
mvn -Djavadoc.skip -pl scijava/scijava-taglets clean install
mvn -Djavadoc.skip -pl scijava/scijava-taglets,scijava/scijava-javadoc-parser -am clean install
Copy link
Member Author

Choose a reason for hiding this comment

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

I'd really prefer to get these modules out of the incubator ASAP - @ctrueden the taglets, at least, seem pretty polished - should we consider migrating them?

Copy link
Member Author

@gselzer gselzer left a comment

Choose a reason for hiding this comment

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

Phew! What a PR!

Copy link
Member Author

Choose a reason for hiding this comment

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

We should change the readme to reflect the new project

Copy link
Member Author

Choose a reason for hiding this comment

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

And should also remember to attribute therapi for the starting code. Check their license

@gselzer
Copy link
Member Author

gselzer commented Sep 12, 2023

Some additional thoughts from discussing with @hinerm and @ctrueden:

  • Let's rename it the SciJava Op Indexer, and specialize it on Ops. We can always copy the code to make something broader than that.
  • Let's try to make the type tag optional for methods - if the user leaves it out, then we can map to it the appropriate Computer or Function.
  • Let's move a lot of the parameters out of the tags map, and leave it for only truly optional stuff (like the OpMethod type) - authors, name, parameters, etc. are all required for all Ops, and it's fine since we are specializing on Ops.

@gselzer gselzer force-pushed the scijava/scijava-javadoc-parser/javadoc-to-yaml branch from f838758 to b8f0cc7 Compare September 12, 2023 15:47
@hinerm
Copy link
Member

hinerm commented Sep 12, 2023

@gselzer with #86 merged the docs will have to be updated as well. I think they can be as part of this PR, or split out to a new issue/branch if you prefer

@gselzer gselzer force-pushed the scijava/scijava-javadoc-parser/javadoc-to-yaml branch from 2bf8bec to 35377ce Compare September 14, 2023 17:32
@gselzer gselzer force-pushed the scijava/scijava-javadoc-parser/javadoc-to-yaml branch from 2c6286e to e82f4e8 Compare October 2, 2023 23:58
@gselzer gselzer merged commit 753836d into main Oct 3, 2023
@gselzer gselzer deleted the scijava/scijava-javadoc-parser/javadoc-to-yaml branch October 3, 2023 00:52
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.

Improve the shortcomings of therapi javadoc processing

4 participants