This post is part of my GSOC journey in coala.
With the emerge of aspect project in coala, come the need to redefine how configuration works and define various new parameter that should control how the aspect should run.
Currently, the mockup for those configuration could be found on cEP-0005 and look like this
[all] # Values can be added to inherited ones only, not within the section because # a configuration should describe a state and not involve operations. # A system wide coafile can define venv, .git, ... and we would recommend to # always use += for ignore even in the default section to inherit those values. # += always concatenates with a comma. ignore += ./vendor max_line_length = 80 # This inherits all settings from the `all` section. There is no implicit # inheritance. [all.python] language = Python files = **.py aspects = smell, redundancy.clone # Inclusive [all.c] language = C files = **.(c|h) ignore_aspects = redundancy # Exclusive
This mockup provide basic example on how aspect configuration could work. Its key feature is:
- New parameter
ignore_aspectsto define list of aspect that coala should analyze.
- New parameter
languageto help coala choose the right bear that could analyze a specific language.
- A taste could defined by writing its name directly (
max_line_length = 80).
bearsmanually is still possible.
- Explicit section inheritance (
Again, this configuration is still a mockup. I think, there are still a few way to further enhance this configuration.
One important aspect of coala and its usability is that the configuration of a new language is as easy as possible.
IMO, usability is a very crucial factor on making coala more widely used in open source project. People like to explore new tools, but if configuring these tools take too much time or too complex, they tend to pass it and get the next tools on the list. coala must shallow its learning curve.
In that regard, I want to make the configuration powerfull and compact, but still provide option to tweak it in detail. It’s should be possible for people to run coala with the most minimal line of configuration, or even with no explicit configuration nor initial setup beforehand.
For coala to analyze aspect properly, we need to know:
- What aspect is choosen
- Which files should analyzed
- What languages it is written in, and
- (optional) Defining aspect’s taste, how a correct aspect should look like
This could be detailed further…
An aspect could be written by its fully qualified name (
partially qualified name (
Some.MyAspect). Defining a parent node
mean all of its children node will be included too.
Defining taste could be done with writing the taste name as the parameter name
and assign a value to it. In case of multiple aspects have the same taste name,
ambiguity must be resolved by prefixing the taste name with its aspect name.
max_length is a taste of
LineLength. Thus the
Shortlog taste would be defined like
Shortlog.max_length = 50.
While defining language, we could use coalang (could be found in module
coalib.bearlib.languages.definitions) to provide flexibility on writting the
language name. For example,
C++ could also written by
CXX, or even
CPlusPlus and they will still refer to the same progamming language.
Other advantadge is in the case of language that have multiple version (like
python2 vs python3), coalang could provide a default version number or users
could define it themself with keyword
version. Note that defining version for
language is not mandatory. Its neccessary in case of project that should be
analyzed under specific version, like python3 project that should analyzed
by python3 only bear.
IMO explicitly defining file in section is not always necessary because we can
get list of file extension from coalang. By defining
language = CPP, then it
also mean implicitly
files = **.c, **.cpp, **.h, **.hpp. Of course this could
be overwritten by explicitly define
files parameter in configuration.
Backward compatibility for choosing bear by its name
There is some unresolved problem on defining bear. The problem is gathering the option configuration for those bear. In aspect based configuration, bear option will collected through taste, but in old configuration, option is given as a kind of “global” parameter in section. It will be a enormous task to write a mapping function from old parameter and its taste pair.
For the time being, I think the most easy approach is to make conditionally collection on each bear with something like this:
class LineLengthBear(LocalBear, aspects=[ 'detect': LineLength ]): def run(self, filename, file, aspects, min_length): if LineLength in aspects: # Overwrite with the aspect's taste if it exist min_length = aspects.get(LineLength).min_length # do something with min_length
To write a aspect configuration, we at least need to know what aspect we want to analyze and what language it’s written in. We can configure it further by defining list of files and list of option (aspect’s taste) for each aspect.
This is my first time trying to write a configuration format and it will be far from perferct or have some unforseen edge case. Hopefully, all the bugs and weird edge cases could be tackled in the future while the the coding is in progress.