Skip to content

Gherkin-Utils - Java - Address issue #1662 - add a Java pretty print gherkin module #1725

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

Closed
wants to merge 41 commits into from

Conversation

nddipiazza
Copy link
Contributor

@nddipiazza nddipiazza commented Sep 3, 2021

Summary

Ported the TypeScript Gherkin pretty print utility to Java.

Details

Make a java port of the javascript pretty printing library available in gherkin-utils.

Motivation and Context

A huge amount of the Gherkin users out there are java users through cucumber-jvm project. We need a pretty printer for Gherkin.

How Has This Been Tested?

Took most of the unit tests from the typescript project.

Types of changes

  • Bug fix (non-breaking change which fixes an issue).
  • New feature (non-breaking change which adds functionality).
  • Breaking change (fix or feature that would cause existing functionality to not work as expected).

Checklist:

  • The change has been ported to Java.
  • I've added tests for my code.
  • My change requires a change to the documentation.
  • I have updated the documentation accordingly.
  • I have updated the CHANGELOG accordingly.

@aslakhellesoy
Copy link
Contributor

Wow thanks so much for contributing this! I haven't had a chance to look at it yet, but will do my best to do it this week.

Copy link
Contributor

@aslakhellesoy aslakhellesoy left a comment

Choose a reason for hiding this comment

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

Overall great code! I've left some comments, mostly about deleting unnecessary files that aren't needed.

Also please add an entry to the CI build configuration in .circleci/config.yml to make sure this gets built.

../../.templates/github/ .github/
../../.templates/java/ .
../testdata/ testdata/
../gherkin.berp gherkin.berp
Copy link
Contributor

Choose a reason for hiding this comment

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

Please remove this line - it's for the gherkin library only

@@ -0,0 +1 @@
cucumber/gherkin-java
Copy link
Contributor

Choose a reason for hiding this comment

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

Please remove this file

../../.templates/java/ .
../testdata/ testdata/
../gherkin.berp gherkin.berp
../gherkin-languages.json src/main/resources/io/cucumber/gherkin/gherkin-languages.json
Copy link
Contributor

Choose a reason for hiding this comment

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

Remove this line too.

@@ -0,0 +1,21 @@
The MIT License (MIT)

Copyright (c) Cucumber Ltd, Gaspar Nagy, Björn Rasmusson, Peter Sergeant
Copy link
Contributor

Choose a reason for hiding this comment

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

Only Cucumber Ltd please, and optionally your own name.

@@ -0,0 +1,53 @@
include default.mk

Copy link
Contributor

Choose a reason for hiding this comment

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

Please remove everything below this line.

@@ -0,0 +1,320 @@
// This code was generated by Berp (http://https://github.com/gasparnagy/berp/).
Copy link
Contributor

Choose a reason for hiding this comment

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

Please remove this file

@@ -0,0 +1,38 @@
[
Copy link
Contributor

Choose a reason for hiding this comment

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

Please remove this file

<modelVersion>4.0.0</modelVersion>
<groupId>io.cucumber</groupId>
<artifactId>gherkin-utils</artifactId>
<version>21.0.1-SNAPSHOT</version>
Copy link
Contributor

Choose a reason for hiding this comment

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

Please align the version number with the existing gherkin-utils/javascript version (and add 1 for the patch version plus a -SNAPSHOT suffix).


<dependencies>
<dependency>
<groupId>io.cucumber</groupId>
Copy link
Contributor

Choose a reason for hiding this comment

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

This should be test scope.

Please add a runtime dependency on messages

Copy link
Contributor Author

Choose a reason for hiding this comment

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

i could not make this change, it caused project not to compile due to missing dependencies during compile time.

(description != null && !"".equals(description.trim()) && stepCount > 0 ? "\n" : "");
}

private static String prettyKeywordContainer(
Copy link
Contributor

Choose a reason for hiding this comment

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

There is a lot of duplication in this method and the next three. Can you extract a private method that they all use?

@jamietanna
Copy link
Contributor

As mentioned in #1729 I've literally just finished working on this as an external project 😭 (sorry for not raising an issue to share that I was!)

So I'd be able to help it you'd like with implementation / we can see about pulling my library in here?

}

@Test
public void scenarioOutlineWithExamples() {
Copy link
Contributor

Choose a reason for hiding this comment

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

To make these test classes more readable, we could split the cases into files before/after, then assert on that, which means we don't have to escape / deal with long strings in this test class


<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
Copy link
Contributor

Choose a reason for hiding this comment

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

❓ are we still as a project using JUnit4? Or are we able to update this to JUnit5?

Copy link
Contributor

Choose a reason for hiding this comment

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

We can move to junit5, we use that in a few other places

@aslakhellesoy
Copy link
Contributor

As mentioned in #1729 I've literally just finished working on this as an external project 😭 (sorry for not raising an issue to share that I was!)

So I'd be able to help it you'd like with implementation / we can see about pulling my library in here?

That would be great @jamietanna! Just keep in mind that we aim to keep the TypeScript/Java implementations consistent.

Copy link
Contributor

@jamietanna jamietanna left a comment

Choose a reason for hiding this comment

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

Can we please make sure this is testing against everything in gherkin/testadata - looks like escaped_pipes.feature returns a slightly different result that I'd expect (\\o vs \o) and there are likely a few other edge cases

@aslakhellesoy
Copy link
Contributor

Can we please make sure this is testing against everything in gherkin/testadata - looks like escaped_pipes.feature returns a slightly different result that I'd expect (\o vs \o) and there are likely a few other edge cases

The files in gherkin/testadata are (intentionally) not formatted according to the pretty implementation. We can read them all in and format them (the tests in the TypeScript implementation does this), but it doesn't compare the formatted document against anything - we just verify that we can parse the formatted document again.

I think the best way to ensure edge cases are covered is to write dedicated unit tests where we have control over the expected output.

@jamietanna
Copy link
Contributor

Sorry, so what I mean is that there are cases where this implementation does not handle specific cases i.e. not correctly escaping in escaped_pipes.feature.

I'd recommend, similar to how I've done it on my own implementation, we have a set of tests via testdata (and other sources, i.e. cases we've written) that source the "before" view, and then validate that it pretty prints to a set of known outputs.

@nddipiazza
Copy link
Contributor Author

OK do you have a list of the test feature files somewhere you want me to add to the unit tests? I'm happy to do so.
I probably won't finish these updates requested for a few days, doing it in my spare time as my day job is eating up my day on other fires.

@jamietanna
Copy link
Contributor

Not to worry @nddipiazza!

You can use https://gitlab.com/jamietanna/gherkin-formatter/-/tree/main/src/test/resources/input as the inputs, and https://gitlab.com/jamietanna/gherkin-formatter/-/tree/main/src/test/resources/output as outputs (for passing tests)

Which are following a formatting style I've found useful on my own implementation.

These were largely adapted from https://github.com/cucumber/gherkin-java/tree/master/testdata but I added quite a few additional scenarios as it was required to make sure I had everything really covered.

@nddipiazza
Copy link
Contributor Author

Excellent. I'm on it.

@jamietanna
Copy link
Contributor

Feel free to copy code / thinking from the library, too - it's MIT so we can bring it into this project as needed.

There's some additional complexities that don't appear to be in the Typescript version (like comments) so it may be there's a bit of extra work rather than just a plain port 😅

@aslakhellesoy
Copy link
Contributor

Yes, comments are lost in the current implementation, and it would be great to keep them! I think we can do that by popping them off as we traverse the other nodes, comparing line numbers.

@nddipiazza
Copy link
Contributor Author

Oh gosh, I'm finally getting back to this. I got mixed up with other work I was doing and thought this was merged.

I fixed the comment that was pending and will look into the failing test.

@aslakhellesoy
Copy link
Contributor

Thanks for picking this up! I’ll let you know when I’ve had a chance to review it.

@nddipiazza
Copy link
Contributor Author

@jamietanna @aslakhellesoy @aurelien-reeves ready for review.

want me to add any more test cases?

Copy link
Contributor

@aurelien-reeves aurelien-reeves left a comment

Choose a reason for hiding this comment

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

From my point of view, it looks good.

One entry in the changelog of gherkin-utills is missing to document the addition of that new java implementation :p

I would just have one question regarding the changes in check-jar.sh (see within the file)

And also, it would be a great addition to update all the readmes of the component to:

  • have a global introduction to gherkin-utils in the root of that component
  • have dedicated instructions for the javascrit and the java implementations

However, I would agree to report that as another piece of work in order to move-on with the current PR. Please, just at least open an issue, or even better, a draft PR, to keep track of that.

For the java code, I'll let other to take a look 😅

Comment on lines +11 to +15
module_path=$(echo $module_name | sed "s/\./\\\\\//g" | sed "s/-/\\\\\//g")
echo "Checking contents of ${jar} to see if it matches pattern: ${module_path}"
unshaded_classes=$(unzip -l ${jar} | grep -e "\.class" | rev | cut -d' ' -f1 | rev | grep -v "^$module_path")
if [[ "${unshaded_classes}" != "" ]]; then
echo "Some classes in ${jar} are not in the io.cucumber package. Rename the classes or change the maven-shade-plugin configuration."
echo "Some classes in ${jar} are not in the expected package matching pattern ${module_path}. Rename the classes or change the maven-shade-plugin configuration."
Copy link
Contributor

Choose a reason for hiding this comment

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

Could you explain those changes here?

Copy link
Contributor Author

@nddipiazza nddipiazza May 18, 2022

Choose a reason for hiding this comment

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

As I added the new module, I noticed that the message was misleading. It mentioned "io.cucumber" needs to be the package, but it's actually checking for io.cucumber + {sub-module}. After spinning my tires on that, I updated the message to make it clear.

And sub-modules with - in them need to be replaced with / just like you are already doing with . that way gherkin-utils becomes io/cucumber/gherkin/utils

@jamietanna jamietanna self-requested a review May 18, 2022 08:18
@aslakhellesoy
Copy link
Contributor

I've continued this work in #1985 - closing this.

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

Successfully merging this pull request may close these issues.

5 participants