8000 Upstream DaggerKotlinIssuesDetector by ZacSweers · Pull Request #1805 · google/dagger · GitHub
[go: up one dir, main page]

Skip to content

Upstream DaggerKotlinIssuesDetector - #1805

Closed
ZacSweers wants to merge 31 commits into
google:masterfrom
ZacSweers:z/daggerLint
Closed

ZacSweers wants to merge 31 commits into
google:masterfrom
ZacSweers:z/daggerLint

Conversation

@ZacSweers
@ZacSweers ZacSweers commented Apr 10, 2020 •
Copy link
Copy Markdown

This is a set of custom lints we wrote internally to help with migration to improved kotlin support in Dagger.

This covers the following cases

Using field: site target in injected properties

image

Using @JvmStatic in object modules

image

Annotating companion objects with @Module

image

These checks also provide lintFixes.

dagger


Edit: Wrote a custom dagger_android_library that I believe covers the android piece now!

One significant caveat - the lint jar must be applied as an artifact directly, as the bazel tooling for android_library is quite lacking and doesn't offer an equivalent to Android Gradle Plugin's lintPublish.

For Android consumers, using this would look like so:

dependencies {
  lintChecks "com.google.dagger:dagger-lint:<version>"
}

For plain Kotlin projects, they can use the lint plugin (I believe this is right, but it's been a minute since I've dealt with it)

apply plugin: "com.android.lint"

dependencies {
  lintChecks "com.google.dagger:dagger-lint:<version>"
}

This is a set of custom lints we wrote internally to help with migration to improved kotlin support in Dagger.

This covers the following cases:
- Using `field:` site target in injected properties
- Using `@JvmStatic` in object modules
- Annotating `companion object`s with `@Module`

These checks also provide lintFixes.

One significant caveat - the lint jar must be applied as an artifact directly, as the bazel tooling for `android_library` is quite lacking and doesn't offer an equivalent to Android Gradle Plugin's `lintPublish`.

For Android consumers, using this would look like so:

```gradle
dependencies {
  lintChecks "com.google.dagger:dagger-lint:<version>"
}
```

For plain Kotlin projects, they can use the lint plugin (I believe this is right, but it's been a minute since I've dealt with it)

```gradle
apply plugin: "com.android.lint"

dependencies {
  lintChecks "com.google.dagger:dagger-lint:<version>"
}
```
@ZacSweers
Copy link
Copy Markdown
Author

I'm currently unable to figure out how to get the tests to run correctly. Sought advice here: bazelbuild/bazel-integration-testing#153 (comment)

@technoir42
technoir42 commented Apr 10, 2020 •
Copy link
Copy Markdown

Could you add a corresponding AAR artifact as well? lintChecks configuration supports only 1 JAR dependency so if someone has their custom Lint checks or uses a third-party JAR-only lint checks it will be problematic for them to use both at the same time.
We, for example, use dagger-reflect-lint which doesn't ship with AAR.

@ZacSweers
Copy link
Copy Markdown
Author

@technoir42 I don't think that works. The ideal case would be to embed the lint.jar in the existing dagger aar artifacts along with a standalone jar artifact for non-android projects, which this currently does the latter.

I'm not sure making the lint library an aar itself would actually even work (lints in aars have a specific format, putting the lint in classes.jar isn't it), plus it would prevent its use in non-android projects. I'm also fairly certain lintCheck() allows multiple targets in Gradle, as it just collects jars.

The main issue here is bazel's android_library rule doesn't support an equivalent to AGP's lintPublish() configuration.

@trevjonez
trevjonez commented Apr 10, 2020 •
Copy link
Copy Markdown

looking at the sources from 4.1.0 alphas:
image
seems like a normal configuration so the consumption pattern here should be fine AFAIK.

I would think standalone jar consuption as well as auto via AAR's would be ideal. what happens if the jar is in multiple AAR's?

EDIT: actually wrong config there. one sec, still digging updated the picture, still seems fine.

@ZacSweers
Copy link
Copy Markdown
Author

what happens if the jar is in multiple AAR's?

We do this today with AutoDispose and haven't had any issues reported. I'd imagine lint does some degree of deduping

@trevjonez
Copy link
Copy Markdown

Actually my guess there is probably not any classpath validation, so it just takes the first it finds when loading up the checks?

it is usually R8/D8 that screams about duplicate entries when an AAR repacks a publicly distributed dependency in the libs dir.

@danysantiago danysantiago left a comment
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thanks creating this PR!

Comment thread java/dagger/lint/BUILD Resolved
Comment thread java/dagger/lint/BUILD Resolved
Comment thread java/dagger/lint/BUILD Resolved
Comment thread javatests/dagger/lint/BUILD Resolved
Comment thread java/dagger/lint/DaggerIssueRegistry.kt Resolved
@ZacSweers
Copy link
Copy Markdown
Author

Wrote a genrule to encapsulate the android_library rule and postprocess the aar to include the lint.jar! This should work as expected in traditional android gradle projects now and I've updated all the existing android_library calls to use the dagger-specific one.

@ZacSweers
Copy link
Copy Markdown
Author

Well... maybe not. This is particularly painful given bazel's learning curve, will keep working at it

@ZacSweers
Copy link
Copy Markdown
Author

It seems like bazel explicitly prohibits modifying rule outputs on linux. Unclear why the behavior on my mac is different, and I'm also not sure how to proceed here. Bazel's android support is too limited to properly support lint if we want to actually embed it in aars. If there's a way to disable the read-only behavior in the genrule sandbox then we'd have a path forward.

@ZacSweers
ZacSweers commented Apr 11, 2020 •
Copy link
Copy Markdown
Author

Ok, it's as far as I can take it I think. I believe the genrule works now, but I get this latest build error on master as well with my local install of bazel (bazel 2.2.0-homebrew)

"ModuleCompanionObjects",
"Module companio 10BC8 n objects should not be annotated with @Module.",
"""
Companion objects in @Module-annotated classes are considered part of the API.
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Can this be a single-line string?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

part of 0d09910

LintFix.create()
.name("Remove @Module")
.replace()
.text("@Module")
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

What if someone types @dagger.Module?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Good point, updated c7b442b

Args:
name: The name of the target.
"""
native_result = native.android_library(name = name, **kwargs)
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

What if you use a suffix for the default target name, and then the genrule can just put the aar in the place you'd like it to be?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

That was my initial approach, but other android libraries that depend on this expect a particular naming structure for artifacts that would then no longer work for anything else generated by this rule

@ronshapiro ronshapiro Apr 14, 2020 •
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

What's an example of that?

Did you try using a genrule, and then wrapping that in an aar_import rule?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

One example is Android support will fail to fail due to trying to expose dagger Android. This seems to be a combination of depending on outputs it has plus the type of like libraries it can depend on.

I haven't tried that. I'm not sure I follow either 🤔. Before I go back down the rabbit hole, is there something inherently wrong with this implementation that merits using another one?

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

I'm pretty sure modifying bazel outputs breaks the hermeticity model. In this case, you never really want someone to depend on the intermediate android_library, but in general Bazel rules create new outputs only.

Here's something like what I had in mind:

native.android_library(
  name = name + "step_1",
  **kwargs
)

native.genrule(
  name = name + "inject_android_lint",
  ...
  outs = [name + "with_injected_android_lint.aar"],
)

native.aar_import(
  name = name + "aar_import",
  aar = name + "with_injected_android_lint.aar",
)

kwargs[deps] += [name + "aar_import"]
native.android_library(
  name = name, # this is the actual target people will "use"
  **kwargs
)

# Restore previous permissions
chmod -w $(location {created_aar})

# Write md5 of the final aar into a the output
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

into a the - typo?

nick-someone pushed a commit that referenced this pull request May 8, 2020
This is a set of custom lints along with fixes to help with migration
to improved kotlin support in Dagger.

This covers the following cases:
* Using field: site target in injected properties
* Using @JvmStatic in object modules
* Annotating companion objects with @module

This CL also includes the necessary infrastructure changes to build,
package and deploy lint rules in the Dagger project.

For Kotlin-only projects, a new artifact 'com.google.dagger:dagger-lint'
will be published so that lint checks can be added via the lintChecks
configuration in Gradle:
```
apply plugin: "com.android.lint"

dependencies {
  lintChecks "com.google.dagger:dagger-lint:<version>"
}
```

Meanwhile for users of Hilt and dagger-android, the lint checks will be
applied from a new transitive dependency 'com.google.dagger:dagger-lint-aar'.

Closes #1805

RELNOTES="Add custom lint checks to Dagger"

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=310269729
@nick-someone nick-someone mentioned this pull request May 8, 2020
nick-someone pushed a commit that referenced this pull request May 8, 2020
This is a set of custom lints along with fixes to help with migration
to improved kotlin support in Dagger.

This covers the following cases:
* Using field: site target in injected properties
* Using @JvmStatic in object modules
* Annotating companion objects with @module

This CL also includes the necessary infrastructure changes to build,
package and deploy lint rules in the Dagger project.

For Kotlin-only projects, a new artifact 'com.google.dagger:dagger-lint'
will be published so that lint checks can be added via the lintChecks
configuration in Gradle:
```
apply plugin: "com.android.lint"

dependencies {
  lintChecks "com.google.dagger:dagger-lint:<version>"
}
```

Meanwhile for users of Hilt and dagger-android, the lint checks will be
applied from a new transitive dependency 'com.google.dagger:dagger-lint-aar'.

Closes #1805

RELNOTES="Add custom lint checks to Dagger"

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=310269729
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants

0