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

Add ScalaModule.scalacHelp command #2921

Merged
merged 4 commits into from
Dec 14, 2023
Merged

Add ScalaModule.scalacHelp command #2921

merged 4 commits into from
Dec 14, 2023

Conversation

lefou
Copy link
Member

@lefou lefou commented Dec 13, 2023

Motivation

As the Scala compiler is most likely only used via the build tool,
and there is probably not the exact scalac version installed on the system,
it can get tricky to find the right options for a specific Scala version.

Usage

This adds a new scalacHelp command to the ScalaModule with which one
can get the scalac built-in help with Mill.

> mill foo.scalacHelp
Output of scalac version: 2.13.11
            with options: -help
Usage: scalac <options> <source files>

Standard options:
  -Dproperty=value             Pass -Dproperty=value directly to the runtime system.
  -J<flag>                     Pass <flag> directly to the runtime system.
  -P:<plugin>:<opt>            Pass an option to a plugin
  -V                           Print a synopsis of verbose options. [false]
  -W                           Print a synopsis of warning options. [false]
  -Werror                      Fail the compilation if there are any warnings. [false]
  -X                           Print a synopsis of advanced options. [false]
  -Y                           Print a synopsis of private options. [false]
  -bootclasspath <path>        Override location of bootstrap class files.
  -classpath <path>            Specify where to find user class files.
  -d <directory|jar>           destination for generated classfiles.
  -dependencyfile <file>       Set dependency tracking file.
  -deprecation                 Emit warning and location for usages of deprecated APIs. See also -Wconf. [false]
  -encoding <encoding>         Specify character encoding used by source files.
  -explaintypes                Explain type errors in more detail. [false]
  -extdirs <path>              Override location of installed extensions.
  -feature                     Emit warning and location for usages of features that should be imported explicitly. See also -Wconf. [false]
  -g:<level>                   Set level of generated debugging info. (none,source,line,[vars],notailcalls)
  -help                        Print a synopsis of standard options [false]
  -javabootclasspath <path>    Override java boot classpath.
  -javaextdirs <path>          Override java extdirs classpath.
  -language:<features>         Enable or disable language features
  -no-specialization           Ignore @specialize annotations. [false]
  -nobootcp                    Do not use the boot classpath for the scala jars. [false]
  -nowarn                      Generate no warnings. [false]
  -opt:<optimizations>         Enable optimizations: `-opt:local`, `-opt:inline:<pattern>`; `-opt:help` for details.
  -opt-inline-from:<patterns>  Patterns for classfile names from which to allow inlining, `help` for details.
  -opt-warnings:<warnings>     Enable optimizer warnings, `help` for details.
  -print                       Print program with Scala-specific features removed. [false]
  -release:<release>           Compile for a version of the Java API and target class file. (8,9,10,[11])
  -rootdir <path>              The absolute path of the project root directory, usually the git/scm checkout. Used by -Wconf.
  -sourcepath <path>           Specify location(s) of source files.
  -toolcp <path>               Add to the runner classpath.
  -unchecked                   Enable additional warnings where generated code depends on assumptions. See also -Wconf. [false]
  -uniqid                      Uniquely tag all identifiers in debugging output. [false]
  -usejavacp                   Utilize the java.class.path in classpath resolution. [false]
  -usemanifestcp               Utilize the manifest in classpath resolution. [false]
  -verbose                     Output messages about what the compiler is doing. [false]
  -version                     Print product version and exit. [false]
  @<file>                      A text file containing compiler arguments (options and source files) [false]

Deprecated settings:
  -optimize                    Enables optimizations. [false]
                                 deprecated: Since 2.12, enables -opt:inline:**. This can be dangerous.
  -target:<target>             Target platform for object files. ([8],9,10,11)
                                 deprecated: Use -release instead to compile against the correct platform API.

The command also accepts arguments which will be passed directly to scalac.

> mill foo.scalacHelp -Xlint:help
Output of scalac version: 2.13.11
            with options: -Xlint:help
Enable recommended warnings
  adapted-args            An argument list was modified to match the receiver.
  nullary-unit            `def f: Unit` looks like an accessor; add parens to look side-effecting.
  inaccessible            Warn about inaccessible types in method signatures.
  infer-any               A type argument was inferred as Any.
  missing-interpolator    A string literal appears to be missing an interpolator id.
  doc-detached            When running scaladoc, warn if a doc comment is discarded.
  private-shadow          A private field (or class parameter) shadows a superclass field.
  type-parameter-shadow   A local type parameter shadows a type already in scope.
  poly-implicit-overload  Parameterized overloaded implicit methods are not visible as view bounds.
  option-implicit         Option.apply used an implicit view.
  delayedinit-select      Selecting member of DelayedInit.
  package-object-classes  Class or object defined in package object.
  stars-align             In a pattern, a sequence wildcard `_*` should match all of a repeated parameter.
  strict-unsealed-patmat  Pattern match on an unsealed class without a catch-all.
  constant                Evaluation of a constant arithmetic expression resulted in an error.
  unused                  Enable -Wunused:imports,privates,locals,implicits,nowarn.
  nonlocal-return         A return statement used an exception for flow control.
  implicit-not-found      Check @implicitNotFound and @implicitAmbiguous messages.
  serial                  @SerialVersionUID on traits and non-serializable classes.
  valpattern              Enable pattern checks in val definitions.
  eta-zero                Usage `f` of parameterless `def f()` resulted in eta-expansion, not empty application `f()`.
  eta-sam                 A method reference was eta-expanded but the expected SAM type was not annotated @FunctionalInterface.
  deprecation             Enable -deprecation and also check @deprecated annotations.
  byname-implicit         Block adapted by implicit with by-name parameter.
  recurse-with-default    Recursive call used default argument.
  unit-special            Warn for specialization of Unit in parameter position.
  multiarg-infix          Infix operator was defined or used with multiarg operand.
  implicit-recursion      Implicit resolves to an enclosing definition.
  universal-methods       Require arg to is/asInstanceOf. No Unit receiver.
  numeric-methods         Dubious usages, such as `42.isNaN`.
  arg-discard             -Wvalue-discard for adapted arguments.
  int-div-to-float        Warn when an integer division is converted (widened) to floating point: `(someInt / 2): Double`.
Default: All choices are enabled by default.

Implementation

I first tried to just pass the "-help" options to the zinc worker,
but I found it does not output the exected built-in help.

Hence, I just load the scala compiler in an isolated classloader.
This is a fire-and-forget attempt, as it is most likely rarely used.

@lefou lefou marked this pull request as draft December 13, 2023 12:28
## Motivation

As the Scala compiler is most likely only used via the build tool,
and there is probably not the exact scalac version installed on the system,
it can get tricky to find the right options for a specific Scala version.

## Usage

This adds a new `scalacHelp` command to the `ScalaModule` with which one
can get the scalac built-in help with Mill.


```
> mill foo.scalacHelp
Output of scalac version: 2.13.11
            with options: -help -Xlint:help
Usage: scalac <options> <source files>

Standard options:
  -Dproperty=value             Pass -Dproperty=value directly to the runtime system.
  -J<flag>                     Pass <flag> directly to the runtime system.
  -P:<plugin>:<opt>            Pass an option to a plugin
  -V                           Print a synopsis of verbose options. [false]
  -W                           Print a synopsis of warning options. [false]
  -Werror                      Fail the compilation if there are any warnings. [false]
  -X                           Print a synopsis of advanced options. [false]
  -Y                           Print a synopsis of private options. [false]
  -bootclasspath <path>        Override location of bootstrap class files.
  -classpath <path>            Specify where to find user class files.
  -d <directory|jar>           destination for generated classfiles.
  -dependencyfile <file>       Set dependency tracking file.
  -deprecation                 Emit warning and location for usages of deprecated APIs. See also -Wconf. [false]
  -encoding <encoding>         Specify character encoding used by source files.
  -explaintypes                Explain type errors in more detail. [false]
  -extdirs <path>              Override location of installed extensions.
  -feature                     Emit warning and location for usages of features that should be imported explicitly. See also -Wconf. [false]
  -g:<level>                   Set level of generated debugging info. (none,source,line,[vars],notailcalls)
  -help                        Print a synopsis of standard options [false]
  -javabootclasspath <path>    Override java boot classpath.
  -javaextdirs <path>          Override java extdirs classpath.
  -language:<features>         Enable or disable language features
  -no-specialization           Ignore @Specialize annotations. [false]
  -nobootcp                    Do not use the boot classpath for the scala jars. [false]
  -nowarn                      Generate no warnings. [false]
  -opt:<optimizations>         Enable optimizations: `-opt:local`, `-opt:inline:<pattern>`; `-opt:help` for details.
  -opt-inline-from:<patterns>  Patterns for classfile names from which to allow inlining, `help` for details.
  -opt-warnings:<warnings>     Enable optimizer warnings, `help` for details.
  -print                       Print program with Scala-specific features removed. [false]
  -release:<release>           Compile for a version of the Java API and target class file. (8,9,10,[11])
  -rootdir <path>              The absolute path of the project root directory, usually the git/scm checkout. Used by -Wconf.
  -sourcepath <path>           Specify location(s) of source files.
  -toolcp <path>               Add to the runner classpath.
  -unchecked                   Enable additional warnings where generated code depends on assumptions. See also -Wconf. [false]
  -uniqid                      Uniquely tag all identifiers in debugging output. [false]
  -usejavacp                   Utilize the java.class.path in classpath resolution. [false]
  -usemanifestcp               Utilize the manifest in classpath resolution. [false]
  -verbose                     Output messages about what the compiler is doing. [false]
  -version                     Print product version and exit. [false]
  @<file>                      A text file containing compiler arguments (options and source files) [false]

Deprecated settings:
  -optimize                    Enables optimizations. [false]
                                 deprecated: Since 2.12, enables -opt:inline:**. This can be dangerous.
  -target:<target>             Target platform for object files. ([8],9,10,11)
                                 deprecated: Use -release instead to compile against the correct platform API.
```

The command also accepts arguments which will be passed directly to scalac.

```
> mill foo.scalacHelp -Xlint:help
Output of scalac version: 2.13.11
            with options: -Xlint:help
Enable recommended warnings
  adapted-args            An argument list was modified to match the receiver.
  nullary-unit            `def f: Unit` looks like an accessor; add parens to look side-effecting.
  inaccessible            Warn about inaccessible types in method signatures.
  infer-any               A type argument was inferred as Any.
  missing-interpolator    A string literal appears to be missing an interpolator id.
  doc-detached            When running scaladoc, warn if a doc comment is discarded.
  private-shadow          A private field (or class parameter) shadows a superclass field.
  type-parameter-shadow   A local type parameter shadows a type already in scope.
  poly-implicit-overload  Parameterized overloaded implicit methods are not visible as view bounds.
  option-implicit         Option.apply used an implicit view.
  delayedinit-select      Selecting member of DelayedInit.
  package-object-classes  Class or object defined in package object.
  stars-align             In a pattern, a sequence wildcard `_*` should match all of a repeated parameter.
  strict-unsealed-patmat  Pattern match on an unsealed class without a catch-all.
  constant                Evaluation of a constant arithmetic expression resulted in an error.
  unused                  Enable -Wunused:imports,privates,locals,implicits,nowarn.
  nonlocal-return         A return statement used an exception for flow control.
  implicit-not-found      Check @implicitNotFound and @implicitAmbiguous messages.
  serial                  @serialversionuid on traits and non-serializable classes.
  valpattern              Enable pattern checks in val definitions.
  eta-zero                Usage `f` of parameterless `def f()` resulted in eta-expansion, not empty application `f()`.
  eta-sam                 A method reference was eta-expanded but the expected SAM type was not annotated @FunctionalInterface.
  deprecation             Enable -deprecation and also check @deprecated annotations.
  byname-implicit         Block adapted by implicit with by-name parameter.
  recurse-with-default    Recursive call used default argument.
  unit-special            Warn for specialization of Unit in parameter position.
  multiarg-infix          Infix operator was defined or used with multiarg operand.
  implicit-recursion      Implicit resolves to an enclosing definition.
  universal-methods       Require arg to is/asInstanceOf. No Unit receiver.
  numeric-methods         Dubious usages, such as `42.isNaN`.
  arg-discard             -Wvalue-discard for adapted arguments.
  int-div-to-float        Warn when an integer division is converted (widened) to floating point: `(someInt / 2): Double`.
Default: All choices are enabled by default.
```

## Implementation

I first tried to just pass the "-help" options to the zinc worker,
but I found it does not output the exected built-in help.

Hence, I just load the scala compiler in an isolated classloader.
This is a fire-and-forget attempt, as it is most likely rarely used.
@lefou lefou marked this pull request as ready for review December 13, 2023 16:57
@lefou lefou requested a review from lihaoyi December 13, 2023 22:01
@lihaoyi
Copy link
Member

lihaoyi commented Dec 14, 2023

Given that -help is just the default, and it seems we can pass whatever we want to it, should we just name it def scalac? Then the calling syntax would be mill foo.scalac -help, and also make it clear that you can pass whatever you want to scalac and it'll run it with the given parameters

@lefou
Copy link
Member Author

lefou commented Dec 14, 2023

Given that -help is just the default, and it seems we can pass whatever we want to it, should we just name it def scalac? Then the calling syntax would be mill foo.scalac -help, and also make it clear that you can pass whatever you want to scalac and it'll run it with the given parameters

I partly agree, it would better reflect the actual capability of the target.

On the other side, Using scalac for anything except getting some help, would require much more arguments and this command is simply not designed to support the user in any other task. For example, we don't have proper result reporting. There is a slight chance that new users think a scalac command is our main worker for doing compilation and then get frustrated when they try to use is to do actual stuff.

Also, I already use the xxxHelp naming pattern in other plugins, e.g. mill-kotlin has a kotlincHelp and mill-aspectj has a ajcHelp.

@lefou
Copy link
Member Author

lefou commented Dec 14, 2023

Given that -help is just the default,

This is only an necessary implementation detail, as the compiler does not support the -help argument AND the -Xlint:help argument to show detailed options. I first started to just add all user-given args after -help (as I do in the other plugins), but it didn't work for that reason.

Copy link
Member

@lihaoyi lihaoyi left a comment

Choose a reason for hiding this comment

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

sounds good

@lefou lefou merged commit e45e15b into main Dec 14, 2023
38 checks passed
@lefou lefou deleted the scalacHelp branch December 14, 2023 10:08
@lefou lefou added this to the 0.11.7 milestone Dec 14, 2023
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