Skip to content

Commit fd2c467

Browse files
committed
cEP-0018: Integration of ANTLR in coala
Propose integration of ANTLR in coala. Closes #118
1 parent 1ec5b92 commit fd2c467

File tree

2 files changed

+248
-0
lines changed

2 files changed

+248
-0
lines changed

README.md

+1
Original file line numberDiff line numberDiff line change
@@ -18,4 +18,5 @@ in the `cEP-0000.md` document.
1818
| [cEP-0012](cEP-0012.md) | coala's Command Line Interface | This cEP describes the design of coala's Command Line Interface (the action selection screen). |
1919
| [cEP-0013](cEP-0013.md) | Cobot Enhancement and porting | This cEP describes about the new features that are to be added to cobot as a part of the [GSoC project](https://summerofcode.withgoogle.com/projects/#4913450777051136). |
2020
| [cEP-0014](cEP-0014.md) | Generate relevant coafile sections | This cEP proposes a framework for coala-quickstart to generate more relevant `.coafile` sections based on project files and user preferences. |
21+
| [cEP-0018](cEP-0018.md) | Integration of ANTLR into coala | This cEP describes how an API based on ANTLR will be constructed and maintained |
2122
| [cEP-0019](cEP-0019.md) | Meta-review System | This cEP describes the details of the process of implementing the meta-review system as a part of the [GSoC'18 project](https://summerofcode.withgoogle.com/projects/#5188493739819008). |

cEP-0018.md

+247
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,247 @@
1+
# Integration of ANTLR into coala core
2+
3+
| Metadata | |
4+
| -------- | --------------------------------------------- |
5+
| cEP | 18 |
6+
| Version | 1.0 |
7+
| Title | Integration of ANTLR into coala core |
8+
| Authors | Viresh Gupta <mailto:[email protected]> |
9+
| Status | Proposed |
10+
| Type | Feature |
11+
12+
## Abstract
13+
14+
This document describes how an API based on ANTLR will be constructed and
15+
maintained.
16+
17+
## Introduction
18+
19+
ANTLR provides parsers for various language grammars and thus we can provide
20+
an interface from within coala and make it available to bear writers so that
21+
they can write advanced linting bears. This will aim at supporting the more
22+
flexible visitor based method of AST traversal (as opposed to listener based
23+
mechanisms).
24+
25+
The proposal is to introduce a parallel concept to the coala-bears library,
26+
which will be called `coala-antlr` hereon.
27+
28+
## Proposed Change
29+
30+
Here is the detailed implementation stepwise:
31+
32+
1. There will be a separate repository named as `coala-antlr` which will
33+
be installable via `pip install coala-antlr`.
34+
2. A new package would be introduced in the coala-antlr repository,
35+
which would maintain all the dependencies for `antlr-ast` based
36+
bears. This would be the `coantlib` package
37+
3. The `coantlib` package will provide endpoints relevant to the
38+
visitor model of traversing the ast generated via ANTLR.
39+
4. Another package named `coantparsers` will be created inside
40+
`coala-antlr` repository. This package will hold parsers and lexers
41+
generated for various languages generated (with python target) beforehand
42+
for the supported set of grammars.
43+
5. `coantlib` will have an `ASTLoader` class that will be responsible
44+
for loading the AST of a given file depending on the user input, using file
45+
extension as a fallback.
46+
For e.g, a .c file will be loaded using the parser from
47+
`coantlib` for c language if no language is specified.
48+
6. Another `ASTWalker` class will be responsible for providing a single method
49+
to resolve the language supplied by the bear and create a walker instance
50+
of the appropriate type.
51+
7. Also `coantlib.walkers` will have several walker classes derived from
52+
`ASTWalker` class that will be language specific and grammar dependant.
53+
For e.g a `Py3ASTWalker`.
54+
8. The bears dependant on the `coantlib` will reside in the same repository as
55+
the `coantlib`. All of them will be in a different package, the `coantbears`
56+
package, all of them installable together via a single option in the
57+
setup.py along with `coantlib`.
58+
9. The bears will be able to use a high level API by defining the `LANGUAGE`
59+
instance variable, which will return to them a walker with high level API's
60+
in case the language is supported. (for e.g if `LANGUAGE='Python'`, they
61+
will automatically get a `BasePyASTWalker` instance in the walker class
62+
variable)
63+
64+
## Management of the new `coala-antlr` repository
65+
66+
Managing a new repository is a heavy task, and this will be highly automated as
67+
follows:
68+
69+
1. The parsers in `coala-antlr/coantparsers` would be generated and
70+
pushed via CI builds whenever a new commit is pushed.
71+
2. The cib tool can be enhanced to deal with the installation of bears that
72+
require only some specified parsers (for e.g a `PyUnusedVarBear` would
73+
only require parser for python).
74+
3. The cib tool can also trigger specialised builds and download the newly
75+
generated parser on the fly.
76+
4. For adding support for a new language, a new Walker class deriving
77+
`ASTWalker` would be added and the rest will be automatically taken care by
78+
the library.
79+
80+
## Code Samples/Prototypes
81+
82+
Here is a prototype for the implementations within `coantlib`:
83+
84+
```python
85+
import antlr4
86+
import coantparsers
87+
import inspector
88+
89+
from antlr4 import InputStream
90+
from coalib.bearlib.languages.definitions import *
91+
from coalib.bearlib.languages.Language import parse_lang_str, Languages
92+
93+
94+
def resolve_with_package_info(lang):
95+
# Use the inspector methods to search amongst all
96+
# classes that inherit ASTWalker within this module
97+
# and return that class whose supported language matches
98+
99+
class ASTLoader():
100+
mapping = {
101+
C : [coantparsers.clexer, coantparsers.cparser],
102+
Python : [coantparsers.pylexer, coantparsers.pyparser],
103+
JavaScript : [coantparsers.jslexer, coantparsers.jsparser],
104+
...
105+
}
106+
107+
@staticmethod
108+
def loadFile(file,filename,lang = 'auto'):
109+
"""
110+
Loads file's AST into memory
111+
"""
112+
if(lang == 'auto'):
113+
ext = get_extension(filename)
114+
else:
115+
ext = Languages(parse_lang_str(lang)[0])[0]
116+
if ext is None:
117+
raise FileExtensionNotSupported('Unknown File Type')
118+
inputStream = InputStream(''.join(file))
119+
lexer = mapping[ext][0](inputStream)
120+
parser = mapping[ext][1](lexer)
121+
return parser
122+
123+
class ASTWalker():
124+
treeRoot = None
125+
tree = None
126+
127+
@staticmethod
128+
def make_walker():
129+
"""
130+
Resolves walker object for appropriate type
131+
"""
132+
if lang == 'auto':
133+
return ASTWalker
134+
else:
135+
return resolve_with_package_info(lang)
136+
137+
@staticmethod
138+
def get_walker(file, filename, lang):
139+
"""
140+
Returns a walker to the required language
141+
"""
142+
ret_class = make_walker(lang)
143+
if not ret_class:
144+
raise Exception('Un-supported Language')
145+
else:
146+
return ret_class(file, filename)
147+
148+
def __init__(file,filename):
149+
self.tree = ASTLoader.loadFile(file, filename)
150+
self.treeRoot = self.tree
151+
...
152+
```
153+
154+
### Prototype of `Py3ASTWalker`
155+
156+
These kinds of Walkers will supply a high level walker API
157+
158+
```python
159+
class BasePyASTWalker(ASTWalker):
160+
LANGUAGES = { 'Python' }
161+
def next_function():
162+
"""
163+
Modify the tree node variable such that it only stops at functions
164+
which can be detected by the Python grammar rules
165+
"""
166+
167+
def get_imports():
168+
"""
169+
Return list of strings containing import statements from the file
170+
"""
171+
172+
def get_methods():
173+
"""
174+
Return list of strings containing all methods from the file
175+
"""
176+
...
177+
178+
class Py2ASTWalker(BasePyASTWalker):
179+
LANGUAGES = { 'Python 2' }
180+
def get_print_statements():
181+
"""
182+
Return list of print statements, since print is a keyword in py2
183+
"""
184+
...
185+
186+
class Py3ASTWalker(BasePyASTWalker):
187+
LANGUAGES = { 'Python3' }
188+
def get_integer_div_stmts():
189+
"""
190+
Returns a list of integer divide statements, since / and // are
191+
different in py3
192+
"""
193+
...
194+
```
195+
196+
### Prototype of `ASTBear` class implementation
197+
198+
```python
199+
from coantlib import ASTWalker
200+
from coalib.bears.LocalBear import Bear
201+
202+
class ASTBear(LocalBear):
203+
walker = None
204+
205+
def initialise(file, filename):
206+
if LANGUAGES:
207+
self.walker = ASTWalker.get_walker(file,
208+
filename,
209+
self.LANGUAGES[0])
210+
else:
211+
self.walker = ASTWalker.get_walker(file, filename, 'auto')
212+
213+
def run(self,
214+
filename,
215+
file,
216+
tree,
217+
*args,
218+
dependency_results = None,
219+
**kwargs
220+
):
221+
raise NotImplementedError('Needs to be done by bear')
222+
```
223+
224+
### A test bear
225+
226+
```python
227+
from coantlib.ASTBear import ASTBear
228+
from coalib.results.Result import Result
229+
230+
class TestBear(ASTBear):
231+
def run(self,
232+
filename,
233+
file,
234+
tree,
235+
*args,
236+
dependency_results=None,
237+
**kwargs
238+
):
239+
self.initialise(file, filename)
240+
violations = {}
241+
method_list = self.walker.get_methods()
242+
for method in method_list:
243+
# logic for checking naming convention
244+
# and yielding an apt result
245+
# wherever required
246+
...
247+
```

0 commit comments

Comments
 (0)