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

Inconsistent annotation formatting #360

Closed
talios opened this issue Apr 4, 2019 · 12 comments
Closed

Inconsistent annotation formatting #360

talios opened this issue Apr 4, 2019 · 12 comments

Comments

@talios
Copy link

talios commented Apr 4, 2019

I was wondering if anyone could explain the inconsistent formatting of annotations I see here between an abstract class member and a private field:

-    @Value.Parameter
-    abstract int page();
+  @Value.Parameter
+  abstract int page();

and

-  @Reference
-  private SomeService someService;
+  @Reference private SomeService someService;

The style guide mentions that multiple annotations may go on a single line - but my reading would be that it could imply "the annotations remain on a separate line to the field, but the annotations may be wrapped onto one line".

It further says there's no specific rules about types, parameters and local variables.

For a measure of consistency - I think sticking to separate lines would be better, except for parameters - which already often wrap to their own line.

Thoughts? What are the rules which the formatter currently uses?

@tbroyer
Copy link
Contributor

tbroyer commented Apr 4, 2019

See fieldAnnotationDirection in the code: it currently uses horizontal direction if all annotations are marker annotations. @Value.Parameter could have arguments, so it triggers vertical annotation direction.

@JakeWharton
Copy link
Contributor

Somewhat related: #342.

@cushon
Copy link
Collaborator

cushon commented Apr 18, 2019

Right, some of the discussion in #342 applies. The style guide doesn't have a lot of hard-and-fast rules about annotations, and we want the formatter to make consistent decisions that generally ignore existing formatting.

I've paged out what went in to this specific discussion, but we usually prioritized consistency over saving vertical space, and this seems counter to that. It's possible that we found there was a lot of existing code where the marker annotations were on the same line as the rest of a field declaration, and we wanted to avoid churn.

If we wanted to revisit this, I'd try making the change and see how much existing code is affected.

@talios
Copy link
Author

talios commented Jul 15, 2019

Just following up on this as it looks like both linked issues were just kinda left hanging. Looking at the code related to fieldAnnotationDirection to me, it seems the implementation doesn't really match the comment associated with it:

/**
 * Should a field with a set of modifiers be declared with horizontal annotations? This is
 * currently true if all annotations are marker annotations.
 */

The comment talks about marker annotations, but the code deals with annotation instances since getAnnotations is returning the expression tree of the code use, thus:

@Inject
@Inject(true)

would yield the first as a marker, the second not, and then you'd when up with formatted code like:

@Inject SomeThing something;

@Inject(true)
SomethingOptionalThing someOptionalThing;

which is.... inconsistent.

Should not fieldAnnotationDirection look at the class definition of the annotations in question, so seeing what arguments are available. That way - @tbroyer's comment above would be correct for all annotations, I suspect it works for @Value.Parameter in my instance, because the annotation has default values, which I assume may be being returned from getArguments?

@talios
Copy link
Author

talios commented Aug 7, 2019

Any comments above @cushon - seems consistency isn't really being applied here. Or at least, the wrong consistency.

@cushon
Copy link
Collaborator

cushon commented Dec 19, 2019

The comment should say 'parameterless' annotation, not 'marker' annotation, I'll fix it.

For fields, the style guide also talks about parameterless annotations: "multiple annotations (possibly parameterized) may be listed on the same line".

One consideration here is that field declarations are usually shorter than method signatures, so keeping the annotations in-line saves some vertical space without hurting readability. It also maintains consistency between field declarations, even if it's sacrificing some global consistency between annotations in general.

If we revisit this, we'd want to do a survey of field declarations that would be affected by the change, and see if keeping the annotations one-per-line looked like an improvement.

@cushon cushon closed this as completed Dec 19, 2019
@talios
Copy link
Author

talios commented Dec 19, 2019

So we're closing, and leaving the inconsistent formatting? Lovely.

so keeping the annotations in-line saves some vertical space without hurting readability

But this doesn't keep them inline. In one source file the same annotation will be inlined, or not inlined, based on its usage - that's... inconsistent.

@cushon
Copy link
Collaborator

cushon commented Dec 19, 2019

based on its usage

By usage, are you referring to whether or not it's a parameterized annotation?

@talios
Copy link
Author

talios commented Dec 19, 2019

By usage, are you referring to whether or not it's a parameterized annotation?

Yes. Going back to my original example:

@Inject SomeThing something;

@Inject(true)
SomethingOptionalThing someOptionalThing;

"a parameterized annotation" to my mind, talks about the parameterization of the annotation itself - CAN it be parameterized, not "a parameterized invocation/usage.

In the above, depending on how its used you end up with inconsistent line breaks for the new @Inject usages, if one was making a commit change from one to the other, rather than a simple 1 line change, we've now got 2 lines.

I was thinking of submitting a PR with a change to look at the available parameter count on an annotation to make that choice, which would yield consistency for a given annotation.

@lowasser
Copy link
Contributor

@talios, https://github.com/google/google-java-format/wiki/FAQ#what-do-you-mean-its-not-a-compiler would seem to imply that it is not possible to look up the annotation to determine its parameter count.

@cushon
Copy link
Collaborator

cushon commented Dec 19, 2019

Right, as @lowasser says we don't have a way to look at the declaration of an annotation. There's related discussion in #5, where we'd like to make a distinction between type and declaration annotations.

If we always formatted annotations on fields one-per-line that would be consistent with methods, but inconsistent with parameters and locals. Minimizing the lines changed (e.g. when replacing @Inject with @Inject(true)) is also consideration, but not the only one, and there are trade-offs.

I prototyped the change to always format annotations one-per-line, and for the examples I surveyed it doesn't seem like an improvement--the field takes up more vertical space, and there weren't nearby fields with different parameterizations of the same annotation that were made more consistent.

Do you have additional perspective or data (such as real-world examples of code that would be affected by the change) that suggests it would be an improvement overall?

@Stephan202
Copy link
Contributor

Another annotation for which the effect of the current implementation is visible is Spring Boot's @MockBean, which optionally accepts a Mockito answer. Anonymized example from an internal code base (the non-anonmized line stays under 100 characters):

@MockBean private SpringBean1 springBean1;
@MockBean private SpringBean2 springBean2;
@MockBean private SpringBean3 springBean3;
@MockBean private SpringBean4 springBean4;

@MockBean(answer = RETURNS_MOCKS)
private SpringBean5 springBean5;

@MockBean private SpringBean6 springBean6;
@MockBean private SpringBean7 springBean7;
@Autowired private SpringBean8 springBean8;

In some other cases we have several beans that require a custom answer, amplifying the effect. In the extreme case a list such as the one above would take up 7 * 4 = 28 lines. In my experience this makes it significantly harder to parse those lines (subjectively, the result appears more "chaotic" than it really is).

That said, I don't have many concrete improvement suggestions. One thing I do suspect will improve the situation is to not enforce the extra two empty lines around multi-line statements. I suspect that for field and variable declarations a compact representation works well enough, as in the "99% case" their complexity is very limited.

kluever pushed a commit that referenced this issue Dec 23, 2019
Parameterless annotations aren't necessarily marker annotations.
All we can tell about a use of an annotation is that it's parameterless,
and that's how 4.8.5 is specified.

Related: #360

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=286650854
kluever pushed a commit that referenced this issue Dec 23, 2019
Parameterless annotations aren't necessarily marker annotations.
All we can tell about a use of an annotation is that it's parameterless,
and that's how 4.8.5 is specified.

Related: #360

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=286650854
robfig pushed a commit to yext/yext-java-format that referenced this issue Dec 17, 2020
* Update outdated Javadoc links

Fixes google#409

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=286092096

* Fix a crash on c-style arrays in parameters

Fixes google#374

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=286467734

* Add SBT plugin to readme

Fixes google#391

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=286493206

* annotation/parameterless annotation

Parameterless annotations aren't necessarily marker annotations.
All we can tell about a use of an annotation is that it's parameterless,
and that's how 4.8.5 is specified.

Related: google#360

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=286650854

* Tell maven-javadoc-plugin to target JDK 8

This unbreaks `mvn install` on AdoptOpenJDK 11.
Presumably it unbreaks on all JDKs >= 11.

Fixes google#429

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=288016119

* Remove trailing tabs from comments to make behavior idempotent.

Fixes google#422, fixes google#423

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=288364171

* Migrate from JSR-305 to the Checker Framework annotations

this is tangentially related to Java 11 preparedness.

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=300822964

* Add Java 11 regression tests

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=301273002

* Use the built-in JDK 11 javac

instead of relying on the shaded/vendored version.

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=301645476

* Increase minimum required JDK version to 11

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=301832060

* Use the default / latest supported language level

Previously the shaded javac was defaulting to Java 8, which we needed to
override to support Java 9. Now that we're using stock JDK 11 this is
unnecessary.

Also explicitly support `var`, instead of relying on it getting parsed as
an actual type name.

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=302105420

* Preserve tabular arguments for mixed sign numeric lists.

Treats unary minus literals (eg -4.0) as their underlying type when checking if all elements in a tabular list are of the same Tree.Kind.

Fixes google#400, google#406

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=303137504

* Add initial support for Java 14 language features

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=303367644

* Make re-parsing of var more robust

to support uses of `var` as an identifier, with and without a type,
e.g. in `var -> {  ... }` and `int var x = 42`;
and uses of `var

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=307693554

* Update the open-source google-java-format plugin for 2020.1.

I couldn't find any good way to make this backwards compatible. Oh well.

FYI, It looks like in 2020.1, we can probably actually use the
ExternalFormatProcessor extension point instead of doing all this hacky
nonsense... they added a #format(PsiFile, TextRange) method you can override.
But I'll leave that for later because 2020.1 is out now and people are mad.

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=308647308

* Fix formatting of records without an explicit constructor

Fixes google#460

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=308658958

* Support `var` in enhanced for loops

Fixes google#463

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=308891540

* Minor Javadoc improvement.

PiperOrigin-RevId: 309329483

* Fix javadoc syntax

Fix javadoc syntax by wrap `<` into an inline code block.

```
[WARNING] ...\google-java-format\core\src\main\java\com\google\googlejavaformat\java\JavaInputAstVisitor.java:2577: warning - invalid usage of tag <
```

Fixes google#454

COPYBARA_INTEGRATE_REVIEW=google#454 from sormuras:patch-1 f5583c7
PiperOrigin-RevId: 309364827

* Pre-release javadoc fixes

PiperOrigin-RevId: 309456095

* Increment versions for 1.8 release

PiperOrigin-RevId: 309467646

* Fix a crash in expression switches

`throws` statements are allows to occur in non-block expression switch cases,
which was causing the trailing `;` to be printed twice.

Fixes google#477

PiperOrigin-RevId: 310974906

* Split up the string "M" + "OE:(begin|end)_intracomment_stripping," as the full string will trigger stripping under Copybara.

Also, avoid reference to an internal link shortener, as we are making references to it an error.

Looking to the future:

When we migrate to use proper Copybara stripping directives, we could consider removing support for the old directives. Then the problem would mostly go away. However, we might end up having the same problem with Copybara directives when google-java-format's strings and method names start mentioning *them*.

PiperOrigin-RevId: 311344956

* Addition of a third party: Github Actions

- Add the possibility of formatting your code from Github directly (taking all the events of Github Actions)
- Addition of the word "old" for the eclipse plugin, since it is 1.6 release

Fixes google#487

COPYBARA_INTEGRATE_REVIEW=google#487 from av1m:master 351b737
PiperOrigin-RevId: 313312689

* Java 14 integration tests

PiperOrigin-RevId: 314566781

* Add support for yield statement

Implement visitYield.

Fixes google#489

from ntkoopman:yield b46d1f0

COPYBARA_INTEGRATE_REVIEW=google#489
PiperOrigin-RevId: 314633394

* Support --skip-removing-unused-imports in google-java-format-diff.py

Fixes google#495

COPYBARA_INTEGRATE_REVIEW=google#495 from taesu82:patch-1 91e32d4
PiperOrigin-RevId: 315560436

* Update the IDEA plugin to use google-java-format 1.8.

PiperOrigin-RevId: 318495968

* Add missing license headers.

PiperOrigin-RevId: 320733285

* Disable Appveyor builds on branches.

Our account for Appveyor allows only 1 concurrent build.  Our current Appveyor config builds every commit to a PR twice -- once as the PR and once as the branch.  This CL updates our Appveyor config to disable builds on branches, so we get only one build per PR commit.

PiperOrigin-RevId: 320734870

* Fix the google-java-format IDEA plugin for 2020.2 IDEs.

PiperOrigin-RevId: 320945302

* Update links to Spotless' new documentation layout

Also included the Spotless maven plugin (2+ years old, but not well marketed)

Fixes google#509

COPYBARA_INTEGRATE_REVIEW=google#509 from nedtwigg:patch-2 546c758
PiperOrigin-RevId: 322832707

* Bump versions to 1.9

PiperOrigin-RevId: 328160170

* Increment versions after 1.10 release

PiperOrigin-RevId: 328214914

* Bump checker-qual from 2.0.0 to 3.6.1

Fixes google#519

COPYBARA_INTEGRATE_REVIEW=google#519 from mernst:checker-qual-361 ca54cb9
PiperOrigin-RevId: 331830590

* Update the IntelliJ plugin to google-java-format 1.9.

PiperOrigin-RevId: 332323928

* Upgrade junit dependency to 4.13.1

PiperOrigin-RevId: 336966883

* Tolerate extra semi-colons in import lists

even if they're own their own line (which g-j-f does if it runs with import
cleanup disabled).

PiperOrigin-RevId: 337192414

* Move import ordering tests out of the AOSP section

follow-up to google@b769e81

PiperOrigin-RevId: 337511552

* Remove typo period in flags documentation.

I *think* they are typoes? Apologies if this is intended.

PiperOrigin-RevId: 343547804

* Introduce GitHub Actions based CI workflow

This PR introduces a CI workflow using GitHub Actions and removes the Travis CI configuration file.

Find new workflow runs for this PR here: https://github.com/sormuras/google-java-format/actions

#### TODO

- [x] Email [Notifications](https://docs.github.com/en/free-pro-team@latest/github/managing-subscriptions-and-notifications-on-github/configuring-notifications) -- register `google-java-format-dev+ci@google.com` as a watcher or let each interested use register themself?
- [ ] Test publish snapshot job on `google:master` -- after storing credential [secrets](https://github.com/google/google-java-format/settings/secrets/actions).
- [ ] Remove AppVeyor [integration](https://github.com/google/google-java-format/settings/installations) and delete `appveyor.yml` configuration file.

Closes google#543

Fixes google#544

COPYBARA_INTEGRATE_REVIEW=google#544 from sormuras:github-action a689f62
PiperOrigin-RevId: 344280060

* Check build with JDK 16-ea

Addresses google#538 (comment)

Fixes google#548

COPYBARA_INTEGRATE_REVIEW=google#548 from sormuras:jdk-ea 0ee3f7c
PiperOrigin-RevId: 344818484

* Fix GitHub Actions-based snapshot deployment

Fixes google#547

PiperOrigin-RevId: 344903246

* Delete google-java-format appveyor and travis configs

PiperOrigin-RevId: 345300707

* Miscellaneous cleanups

Startblock:
   cl-status copybara contains unknown commit in live
PiperOrigin-RevId: 345718768

* Prepare google-java-format for JDK 16 ea

* Work around change to tokenization in JDK-8254073
* Access refactored expression pattern getters reflectively
* Relax a check on a diagnostic whose position changed

PiperOrigin-RevId: 347318664

Co-authored-by: Anthony Vanelverdinghe <anthonyv.be@outlook.com>
Co-authored-by: cushon <cushon@google.com>
Co-authored-by: Ben McCann <322311+benmccann@users.noreply.github.com>
Co-authored-by: Carmi Grushko <carmi@fb.com>
Co-authored-by: Eckert, Alexander <alexander.eckert@gmx.de>
Co-authored-by: Andrew Reid <andrew.k.reid@gmail.com>
Co-authored-by: plumpy <plumpy@google.com>
Co-authored-by: google-java-format Team <no-reply@google.com>
Co-authored-by: Christian Stein <sormuras@gmail.com>
Co-authored-by: cpovirk <cpovirk@google.com>
Co-authored-by: Avi Mimoun <36456709+av1m@users.noreply.github.com>
Co-authored-by: Tim Koopman <n.t.koopman@nandoe.net>
Co-authored-by: taesu82.lee <66580975+taesu82@users.noreply.github.com>
Co-authored-by: google-java-format Team <java-team-github-bot@google.com>
Co-authored-by: Eddie Aftandilian <eaftan@google.com>
Co-authored-by: Ned Twigg <ned.twigg@diffplug.com>
Co-authored-by: Michael Ernst <mernst@alum.mit.edu>
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

No branches or pull requests

6 participants