R.swift
R.swift copied to clipboard
Added the ability to specify options, or default arguments, for plugin invocations
What does this PR do?
This PR fills in a gap that is currently present when using the Package/Xcode Plugins to perform source code generation, either manually using the RswiftGenerateResourcesCommand, or automatically using the RswiftGeneratePublicResources or RswiftGenerateInternalResources plugins. The gap to which I speak is that if any customization is needed, i.e. rswift arguments, that can only be done when manually running the RswiftGenerateResourcesCommand plugin and the arguments must be specified each time the plugin is used.
This is obviously not an ideal scenario, so this PR seeks to alleviate this issue by adding support for an "options" file. The way in which this works is slightly different for Xcode Plugins vs. SPM Plugins, but the premise and formatting is the same:
- A
.rswiftoptionsfile is declared in your sources root (Xcode Plugins can create an additional file in the root of the project as well) - When either of the plugins mentioned above the options are loaded from this options file, validated, and then combined with any defaults and options provided via the plugin invocation and including those in the options provided to the
rswiftutility. - That's it!
The .rswiftoptions file is a JSON file that has a very simple schema:
{
"generators": ["..."],
"omit-main-let": true/false,
"imports": ["..."],
"access-level": "public"/"internal",
"rswiftignore": "...",
"bundle-source": "finder"/"module",
"output-path": "...",
"additional-arguments": ["..."]
}
All of the fields in this JSON object are optional and are applied in a systemic and deterministic way when executing the plugins:
- Create an options structure any arguments passed in from the plugin invocation parsed out. Options provided to the plugin invocation always take precedent since they have to be passed in for each execution, indicating that the intent is to override any preset or default values.
- (For Xcode Plugins) Attempt to load a
.rswiftoptionsfile that is located in the same directory as the project file invoking the plugin. These options are combined with the options in the previous step in such a way to where the previous options will not be overridden by the new options, should a particular option already be set. - Attempt to load a
.rswiftoptionsfile that is located in the root directory containing the source files for the given target. These options are combined with the options in the previous step in such a way to where the previous options will not be overridden by the new options, should a particular option already be set. - Lastly, apply any "fallback" options, i.e. options that should be used should the options not be specified by any other means.
When done in this manner, this allows for one to use these options files to specify the arguments that should always be provided, but allows for those values to be overridden if invoking the plugin directly.
How are these changes implemented?
The way in which the implementation is done is multifaceted:
- First, a new library target was created called
RswiftSharedto contain code that should be shared between therswiftexecutable target as well as the plugin targets. TheAccessLevel,BundleSource, andResourceTypetypes were all moved into this new target. - Next, symbolic links were created in the plugin sources directories to reference the
RswiftSharedsources directory. This is done to get around an issue where plugin targets cannot have a dependency on a library target so the sources are brought into each of the plugin targets via this symbolic link. - An additional type was created to mimic the structure of the JSON options file with a conformance to
Decodablefor easy parsing. - Lastly, the implementation of each plugin was updated to attempt to load these
.rswiftoptionsfiles and combine these options with any provided from the plugin invocation, if relevant.
Any testing done?
Yes, testing was performed locally using an Xcode project and a Swift Package, each of which was tested by using various combinations of the aforementioned plugins, options files, and options provided when manually invoking the RswiftGenerateResourcesCommand. All results of this testing align with the deterministic manner in which those options should have been applied, as described above