forked from coala/cEPs
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
cEP-0010.md: Convert bears to use aspects
- Loading branch information
1 parent
57cfe06
commit 3c5ec97
Showing
1 changed file
with
336 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,336 @@ | ||
# Convert bears to use aspects | ||
|
||
| Metadata | | | ||
| ------------ |------------------------------------------------| | ||
| cEP | 10 | | ||
| Version | 1.0 | | ||
| Title | Convert bears to use aspects | | ||
| Authors | Asnel Christian Ngoulla <[email protected]> | | ||
| Status | Implementation Due | | ||
| Type | Feature | | ||
|
||
## Abstract | ||
|
||
This document describes how `aspects` will be defined for and connected with | ||
bears and how their results will be annotated with them. | ||
|
||
This cEP also provides a list of the `aspects` to be implemented with their | ||
correspponding `tastes` where taste are customization `settings` for `aspects`. | ||
|
||
## Introduction | ||
|
||
An `aspect` is an analysis we want to run over a piece of code. As stated in | ||
[cEP-0005](https://github.com/coala/cEPs/blob/master/cEP-0005.md), one of the | ||
main problems coala faces is its configuration due to the huge number of bears | ||
it offers, which are capable of analyzing several aspects of code and are | ||
sometimes highly configurable with numerous settings; whereby the user has to | ||
be aware of which bear does what and which setting has be to set to analyze | ||
the aspect he wants analyzed; resulting in a coala difficult to learn and use. | ||
|
||
To make things easier for user the concept of `aspects` was created as proposed | ||
in [cEP-0005](https://github.com/coala/cEPs/blob/master/cEP-0005.md). Our goal | ||
here is to list all the aspects for covering all the code anlysis features the | ||
coala bears are capable of, annotating bears' results with them. | ||
|
||
## The aspests | ||
|
||
The bears offered by coala are usually capable of handling several aspects. | ||
`aspects` will be implemented in a tree-like form starting with the | ||
[Root aspect](https://github.com/coala/coala/blob/master/coalib/bearlib/aspects/root.py). | ||
Here is the list of aspects to be implemented along with their corresponding | ||
`subaspects` and tastes(which are the leaves of the tree written | ||
in snake_case). | ||
|
||
|
||
``` | ||
Root | ||
|--- Formatting | ||
|--- |--- UseSpaces | ||
|--- |--- TrailingSpace | ||
|--- |--- EmtpyLines | ||
|--- |--- |--- num_newlines_after_class_def | ||
|--- |--- |--- num_newlines_after_func_def | ||
|--- |--- Quotation | ||
|--- |--- |--- prefered_quotation | ||
|--- |--- Length | ||
|--- |--- |--- LineLength | ||
|--- |--- |--- |--- max_line_length | ||
|--- |--- |--- Ignore | ||
|--- |--- |--- |--- ignore_links | ||
|--- |--- |--- |--- ignore_line | ||
|--- |--- |--- FileLength | ||
|--- |--- |--- |--- max_file_length | ||
|--- |--- Indentation | ||
|--- |--- |--- size | ||
|--- |--- ParenthesesFormatting | ||
|--- |--- BracesFormatting | ||
|--- |--- SpaceAroundOperators | ||
|--- Smell | ||
|--- |--- Complexity | ||
|--- |--- |--- cyclomatic_complexity | ||
|--- |--- ClassSmell | ||
|--- |--- |--- ClassLength | ||
|--- |--- |--- |--- max_class_length | ||
|--- |--- |--- |--- min_class_length | ||
|--- |--- |--- FeatureEnvy | ||
|--- |--- MethodSmell | ||
|--- |--- |--- max_method_length | ||
|--- |--- |--- max_parameter | ||
|--- |--- Naming | ||
|--- |--- |--- variable_naming_convention | ||
|--- |--- |--- function_naming_convention | ||
|--- |--- |--- class_naming_convention | ||
|--- |--- |--- max_indentifier_name_length | ||
|--- |--- |--- min_indentifier_name_length | ||
|--- Security | ||
|--- |--- buffer_overflow | ||
|--- |--- unallocated_memory | ||
|--- Redundancy | ||
|--- |--- Clone | ||
|--- |--- |--- min_clone_tokens | ||
|--- |--- |--- ignore_using | ||
|--- |--- UnusedImport | ||
|--- |--- UnreachableCode | ||
|--- |--- UnusedFunction | ||
|--- |--- UnreachableStatement | ||
|--- |--- UnusedParameter | ||
|--- |--- UnusedLocalVariable | ||
|--- |--- UnusedGlobalVariablee | ||
|--- Spelling | ||
|--- |--- aspectsYEAH | ||
|--- |--- coala | ||
|--- UndefinedElement | ||
|--- |--- UndefinedVariable | ||
|--- |--- UndefinedParameter | ||
|--- |--- UndefinedFunction | ||
|--- Documentation | ||
|--- Grammar | ||
|--- |--- Language | ||
|--- Metadata | ||
|--- |--- CommitMessage | ||
|--- |--- | --- Shortlog | ||
|--- |--- | --- |--- Emptiness | ||
|--- |--- | --- |--- ColonExistence | ||
|--- |--- | --- |--- TrailingPeriod | ||
|--- |--- | --- |--- Tense | ||
|--- |--- | --- |--- Length | ||
|--- |--- | --- |--- |--- max_shortlog_length | ||
|--- |--- | --- |--- FirstCharacter | ||
|--- |--- | --- |--- |--- shortlog_starts_upper_case | ||
|--- |--- | --- Body | ||
|--- |--- | --- |--- Existence | ||
|--- |--- | --- |--- Length | ||
|--- |--- | --- |--- |--- max_body_length | ||
``` | ||
* `Root.Formatting`: This aspect checks on the format (the structure) of your | ||
codebase. | ||
* `Root.Formatting.UseSpaces`: This aspect enforces the use of spaces over | ||
tabs. | ||
* `Root.Formatting.TrailingSpace`: This aspect detects trailing spaces in the | ||
code. | ||
* `Root.Formatting.EmptyLines`: This aspect checks on empty lines. | ||
* `Root.Formatting.EmptyLines.num_newlines_after_class_def`: | ||
This taste represents the number of newlines that should be added after a class | ||
definition. | ||
* `Root.Formatting.EmptyLines.num_newlines_after_func_def`: | ||
This taste represents the number of newlines that should be added after a | ||
function definition. | ||
* `Root.Formatting.Quotation`: This aspect checks on the quotations being used | ||
in your files given `Root.Formatting.Quotation.prefered_quotation`. | ||
* `Root.Formatting.Quotation.prefered_quotation`: This taste represents the | ||
user's preferred quotation. | ||
* `Root.Formatting.LineLength`: This aspect checks on lines' length in your | ||
codebase. | ||
* `Root.Formatting.LineLength.max_line_length`: This taste represents that | ||
maximum length for line. | ||
* `Root.Formatting.LineLength.Ignore`: This aspect represents all the | ||
elements to be ignored. | ||
* `Root.Formatting.LineLength.Ignore.ignore_links`: this taste is to determine | ||
whether links should be ignored while checking on lines' length. | ||
* `Root.Formatting.LineLength.Ignore.ignore_line`: this taste is to which line | ||
should be ignored while checking on lines' length. | ||
* `Root.Formatting.FileLength`: This aspect checks on files' length given | ||
`Root.Formatting.FileLength.max_file_length`. | ||
* `Root.Formatting.FileLength.max_file_length`: this taste represents the | ||
maximum length for a file. | ||
* `Root.Formatting.Indentation`: This taste checks on the number of space | ||
used for indentation given `Root.Formatting.Indentation.size`. | ||
* `Root.Smell`: This aspect describes `code smells` (smells refer to | ||
structures that violate design principles) in your codebase. | ||
* `Root.Smell.Complexity`: describes the complexity of your code given the | ||
value `cyclomatic_complexity`. | ||
* `Root.Smell.Complexity.cyclomatic_complexity`: Variable reprensing the | ||
maximum number of embedded branches or embedded loops. | ||
* `Root.Smell.ClassSmell`: This aslpect describes `code smells` related to | ||
classes' definition in your codebase. | ||
* `Root.Smell.ClassSmell.ClassLength`: This aspect deals with the length of | ||
classes' definition. | ||
* `Root.Smell.ClassSmell.ClassLength.max_class_length`: This taste represents | ||
the maximum length for a class's definition. | ||
* `Root.Smell.ClassSmell.ClassLength.min_class_length`: This taste represents | ||
the minimum length for a class's definition. | ||
* `Root.Smell.ClassSmell.FeatureEnvy`: This aspect describes classes that use | ||
other classes' methods excessively. | ||
* `Root.Smell.ClassSmell.DataClump`: This aspect describes variables | ||
are passed around together in various parts of the program, suggesting | ||
that they should pass as a single object. | ||
* `Root.Smell.MethodSmell`: This aspect describes code smells | ||
related to functions' (and or methods') definition. | ||
* `Root.Smell.MethodSmell.max_method_length`: variable representing the | ||
maximum length for a method or a function definition. | ||
* `Root.Smell.MethodSmell.max_parameter`: This taste represents maximum number | ||
of paramters for a function. | ||
* `Root.Smell.Naming`: This aspect deals with identifiers' names(their | ||
length, the naming convention in use ...) | ||
* `Root.Smell.Naming.variable_naming_convention`: This taste represents the | ||
naming convention used for variables' and functions' parameters' identifiers. | ||
* `Root.Smell.Naming.function_naming_convention`: This taste | ||
represents the naming convention used for functions' or methods'. | ||
* `Root.Smell.Naming.class_naming_convention`: This taste represents the | ||
naming convention being used for classes. | ||
* `Root.Smell.Naming.max_identifier_length`: This taste represents the max | ||
length for an identifier. | ||
* `Root.Smell.Naming.max_identifier_length`: This taste represents the min | ||
length for an identifier. | ||
* `Root.Redundancy`: This aspect describes redundancy in your source code. | ||
* `Root.Redundancy.Clone`: This aspect detects code | ||
clones or more specifically very similar blocks of code in your codebase. | ||
* `Root.Redundancy.Clone.min_clone_tokens`(a taste of the `Clone` aspect): | ||
Thsi taste represents the minimun number of token that have to be equal to be | ||
considered as a clone. | ||
* `Root.Redundancy.UnusedImport`: This taste describes useless import/include | ||
that is not needed. | ||
* `Root.Redundancy.UnreachableCode`: This taste describes source code that | ||
can never be executed during the program execution. | ||
* `Root.Redundancy.UnusedFunction`: This taste describes functions that | ||
are never called during code execution | ||
* `Root.Redundancy.UnreachableStatement`: This taste describes statement that | ||
are never executed during code execution. | ||
* `Root.Redundancy.UnusedParameter`: This taste describes functions' | ||
parameters which are never used. | ||
* `Root.Redundancy.UnusedLocalVariable`: This taste describes variables which | ||
are defined locally but never used. | ||
* `Root.Redundancy.UnusedGlobalVariable`: this taste describes variables which | ||
have a global scope but are never used. | ||
* `Root.Spelling`: This aspect checks on the spelling of specific words. | ||
* `Root.Spelling.coala`: This aspect checks on the spelling of `coala`. | ||
* `Root.Spelling.aspectsYEAH`: This aspect checks on the spelling of | ||
`aspect[s]` and `aspectsYEAH`. | ||
* `Root.UndefinedElement`: This aspect checks on undefined element in your | ||
codebase. | ||
* `Root.UndefinedElement.UndefinedVariable`: This aspect detects undefined | ||
variables in your code. | ||
* `Root.UndefinedElement.UndefinedParameter`: This aspect detects undefined | ||
parameters in functions' definitions. | ||
* `Root.UndefinedElement.UndefinedFunction`: This aspect detects undefined | ||
functions in your codebase. | ||
* `Root.Metadata`: This describes any aspect that is related to metadata that | ||
is not inside your source code. | ||
* `Root.Metadata.CommitMessage`. | ||
* `Root.Metadata.CommitMessage.Emptiness`: This aspect is to detect and | ||
prevent from using empty commit message. | ||
* `Root.Metadata.CommitMessage.Shortlog`: This aspect checks on the first line | ||
of your commit message. | ||
* `Root.Metadata.CommitMessage.Shortlog.ColonExistence`: This aspect checks | ||
your commit shortlog to see whether or not there is a colon (given that the | ||
usage of colon is compulsory in your project). | ||
* `Root.Metadata.CommitMessage.Shortlog.TrailingPeriod`: This aspect checks | ||
for trailing period. | ||
* `Root.Metadata.CommitMessage.Shortlog.Tense`: This aspect checks on the | ||
tense used in commit message shortlog. | ||
* `Root.Metadata.CommitMessage.Shortlog.Length`: This aspect checks on the | ||
length of your commit message shortlog given the value of | ||
`Root.Metadata.CommitMessage.Shortlog.Length.max_shortlog_length`. | ||
* `Root.Metadata.CommitMessage.Shortlog.FirstCharacter`: This aspect detects | ||
inconsistent casing for the first character of your commit message shortlog( | ||
and the the first character following the colon if there is one) given the | ||
value of | ||
`Root.Metadata.CommitMessage.Shortlog.FirstCharacter.shortlog_starts_upper_case` | ||
[taste representing the case to use for the first character of your | ||
commit message shortlog and the first character following the colon]. | ||
* `Root.Metadata.CommitMessage.Body`: Parent aspect for all of the aspects | ||
related to your commit message body. | ||
* `Root.Metadata.CommitMessage.Body.Existence`: Checks on the existence of | ||
your commit message body (it enforces its usage). | ||
* `Root.Metadata.CommitMessage.Body.Length`: Checks on the length of your | ||
commit message body given the value of | ||
`Root.Metadata.CommitMessage.Body.Length.max_body_length`. | ||
|
||
## Implementation | ||
|
||
As stated previously the aspects will be implemented in a tree like form, | ||
with the Root aspect at the root of the tree. Some classes, metaclasses | ||
and some few methods were define so far to make that possible including: | ||
|
||
* [the aspectbase class](https://github.com/coala/coala/blob/master/coalib/bearlib/aspects/base.py) | ||
* [the Documentation class for documenting aspects](https://github.com/coala/coala/blob/master/coalib/bearlib/aspects/docs.py) | ||
* [the aspectclass metaclass](https://github.com/coala/coala/blob/master/coalib/bearlib/aspects/meta.py) | ||
* [the TasteMeta class](https://github.com/coala/coala/blob/master/coalib/bearlib/aspects/taste.py) | ||
* [the Taste class](https://github.com/coala/coala/blob/master/coalib/bearlib/aspects/taste.py) | ||
|
||
`aspects` will simply be defined this way: | ||
```python | ||
from coalib.bearlib.aspects import Root, Taste | ||
|
||
|
||
@Root.subaspect | ||
class SomeAspect: | ||
|
||
# This will serve as documentation for the aspect | ||
class docs: | ||
example = 'an example of this aspect of code' | ||
example_language = 'the programming language of the example' | ||
importance_reason = 'the reason why this is important' | ||
fix_suggestions = '' | ||
|
||
# Here we define the different tastes for this aspect | ||
# aspects are not compelled to have tastes | ||
some_taste = Taste[Taste_type]( | ||
'Documentation about this taste', | ||
list('Possible value for this taste',), | ||
default='Default value for this taste') | ||
``` | ||
The documentation of each of the implemented aspects will be added to | ||
the [coala/aspect-docs](https://github.com/coala/aspect-docs) repository. | ||
|
||
Concerning bears' results annotation, so far, the `.aspect` attr was added to | ||
the [Result class](https://github.com/coala/coala/blob/master/coalib/results/Result.py) | ||
(where a Result object is what is yielded by a bear when through executing). | ||
So annotating a bear's result with aspects simply consists of setting this | ||
variable to the appropriate aspect of code. | ||
Here is how bears' will be defined in as presented in | ||
[cEP-0005](https://github.com/coala/cEPs/blob/master/cEP-0005.md). | ||
|
||
```python | ||
from coalib.bears.LocalBear import LocalBear | ||
from coalib.results.Result import Result | ||
from coalib.bearlib.aspects import Root | ||
|
||
|
||
class RedundancyBear(LocalBear, aspects={ | ||
# This represents all the aspects this bear can detect. | ||
'detect': [Root.Redundancy.Clone], | ||
# This represents all the aspects this bear can fix. | ||
'fix': [Root.Redundancy.UnusedImport]}, | ||
languages=['C', 'Python']): | ||
|
||
def run(self, filename, file, aspects): | ||
# No documentation required anymore for the bears. | ||
|
||
if unused_imports(file): | ||
# A bear may yield results for any aspect even if it's not selected. | ||
# coala will filter out only selected aspects. | ||
yield Result.from_values(aspect=Root.Redundancy.UnusedImport, ...) | ||
|
||
# Bears can save performance by only performing needed checks | ||
aspect = aspects.get(Root.Redundancy.Clone, False) | ||
if aspect: | ||
# Bears can access tastes right from the aspect instance | ||
min_clone_tokens = aspect.min_clone_tokens | ||
|
||
# The aspect is tied to the result. coala now knows everything from | ||
# the aspect documentation! | ||
yield Result.from_values(aspect=aspect, ...) | ||
``` | ||
|