Conversation
|
@ArquintL this is marked as a draft PR but you asked for the review. Should I provide feedback on the implementation already? regarding the cli options, I would opt for one of the following:
|
|
@jcp19 This PR is in draft mode as the design choices are more like suggestions. Code-wise, I do not have any additional changes planned so I'd appreciate a code review. We currently do not have a JSON field for every existing CLI option but if necessary, we can always add more (in separate PRs) |
|
High-level questions about the design:
|
|
I think that the following design could also work:
Under this design, the (*) While thinking of how all options relate to each other, and especially, how the configs of each package relate to each other, I was confronted again with the fact that right now, we read all configs of all files, regardless of their packages. I think this is a bad idea, which leads to unexpected results (e.g., if we import a package that was verified for overflow checks, it enables overflow checks for the current package). Maybe we should consider deprecating in-file configs when we introduce the json config, except for tests. |
Sorry for the imprecision, it's only mandatory if
One can argue whether we should allow
If both files are optional? How would we identify which folder forms a module's root? By detecting
Not sure whether this is less confusing but I think that this should work. The only weird case affects |
Either that or by traversing the directory tree, starting in the current package, and moving from parent to parent until a
IIRC, you do not pass a package in the recursive mode, but rather, the project root. So, I guess we would iterate through all packages in that directory. I think we need to think about what should be the roles of the project root and module root (should they be unified somehow?). |
After additional consideration, I am happy with @ArquintL general proposal, but I would rather choose one of the behaviours I proposed above for the case when we provide more CLI flags in addition to |
jcp19
left a comment
There was a problem hiding this comment.
So far, I reviewed up to src/main/scala/viper/gobra/frontend/Config.scala. I will continue the review later
bd4cb25 to
0fa163c
Compare
…ic to merge different options
… by introducing 'InputConfig' as an intermediate representation for configuration options
|
@jcp19 Sorry this got quite ugly in the end ^^ |
jcp19
left a comment
There was a problem hiding this comment.
In general, it looks ok to me. I have a few minor comments / remarks
|
|
||
| /** Options that must not appear in the `other` field of a JSON config because their paths | ||
| * cannot be correctly resolved (they are turned into Source objects before path resolution). */ | ||
| private val disallowedInOther: Set[String] = Set("--input", "-i", "--directory", "-p") |
There was a problem hiding this comment.
what about include paths (-I) and --projectRoot? Is there a criteria for things commands whose paths are resolved? And for those commands where we resolve the paths, are they resolved against the current path?
| implicit class ScallopOptionExtension[T](opt: ScallopOption[T]) { | ||
| /** Converts a ScallopOption to an InputConfigOption using the option's name and value. | ||
| * Only includes the value if the option was explicitly supplied by the user, | ||
| * not just set to a default value. */ | ||
| def toInputConfigOption: InputConfigOption[T] = | ||
| InputConfigOption(opt.name, if (opt.isSupplied) opt.toOption else None) | ||
| } | ||
| } |
There was a problem hiding this comment.
I feel like this use of implicit affords us very little, and I would rather have the more predictable behaviour and maintainability of having toInputConfigOption as a regular (static) method, rather than an extension method.
| /** resolves all relative paths in relation to `basePath` */ | ||
| override def resolvePaths(basePath: Path): GobraInstallCfg = | ||
| copy( | ||
| jar_path = resolveOptPath(basePath, jar_path), |
There was a problem hiding this comment.
hmm, what's the point of passing the jar here? given that a user has to call gobra (and select the jar there), this feels redundant
| mce_mode: Option[MCE.Mode] = None, | ||
| module: Option[String] = None, | ||
| more_joins: Option[MoreJoins.Mode] = None, | ||
| pkg_path: Option[String] = None, // TODO: what is this? |
There was a problem hiding this comment.
I guess this is the input to -p
| parallelize_branches: Option[Boolean] = None, | ||
| print_vpr: Option[Boolean] = None, | ||
| project_root: Option[String] = None, | ||
| recursive: Option[Boolean] = None, // TODO: why would a package specify recursion? |
There was a problem hiding this comment.
I don't oppose dropping this for json configs.
This PR pushes @jcp19's idea further to use a JSON file to configure Gobra by integrating the parsing of the JSON file into Gobra. The accepted JSON structure follows gobrago with the following differences:
gobra-mod.jsonandgobra.json, respectivelyinstallation_cfganddefault_job_cfgotherfield. In particular, these options are parsed and merged with the other non-other fields, constituting a configuration after merging. I.e., this merging is happening before applying the precedence rule that overwrites module-level options.In addition, the following design choices have been made:
--config <path>is used to configure Gobra<path>must exist and can either be one of the following:--printConfigis additionally permitted to display the actually used configuration. All other options result in an error. If--printConfigis not provided, Gobra prints a short note stating with configuration files have been considered.<path>towards the filesystem's root directory