Merged PR 4509: CppToJson First Version
Added all basic files required for the functionality of CppToJson, including some basic testing
This commit is contained in:
Родитель
007601c4da
Коммит
84d4f9faba
|
@ -0,0 +1,82 @@
|
|||
import os
|
||||
import re
|
||||
import clang.cindex as cindex
|
||||
import CommonEnvironment.FileSystem as fileSystem
|
||||
import CommonEnvironment.CallOnExit as callOnExit
|
||||
import CommonEnvironment.Shell as CE_Shell
|
||||
|
||||
def ObtainFunctions(input_filename):
|
||||
'''
|
||||
This function will extract return value, name and parameters for every
|
||||
function given. input_filename can be a file name or a string that is the code
|
||||
itself.
|
||||
Return value:
|
||||
Returns a list of functions, every item in this list is a dictionary that
|
||||
has information about the function.
|
||||
'''
|
||||
is_temp_file = False
|
||||
# Since clang can only parse from a file, if we are given a string we need to create
|
||||
# a new temp file and put the string inside.
|
||||
if not fileSystem.IsFilename(input_filename):
|
||||
is_temp_file = True
|
||||
file_content = input_filename
|
||||
input_filename = CE_Shell.Shell.CreateTempFilename(suffix=".cpp")
|
||||
with open(input_filename, "w") as file_pointer:
|
||||
file_pointer.write(file_content)
|
||||
# ----------------------------------------------------------------------
|
||||
def DeleteFile():
|
||||
if is_temp_file:
|
||||
os.remove(input_filename)
|
||||
# ----------------------------------------------------------------------
|
||||
|
||||
with callOnExit.CallOnExit(DeleteFile):
|
||||
funcs_list = []
|
||||
|
||||
pattern_const = re.compile("^const ")
|
||||
pattern_star = re.compile(r"( \*)*\**")
|
||||
pattern_amper = re.compile("( &)*&*")
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
def SimpleVarType(name):
|
||||
name = re.sub(pattern_const, "", name)
|
||||
name = re.sub(pattern_star, "", name)
|
||||
name = re.sub(pattern_amper, "", name)
|
||||
return name
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
|
||||
index = cindex.Index.create()
|
||||
args = []
|
||||
|
||||
if os.name == 'posix':
|
||||
args = ['-I{}'.format(v) for v in os.environ['INCLUDE'].split(":") if v.strip()]
|
||||
|
||||
translation_unit = index.parse(input_filename, args=args)
|
||||
cursor = translation_unit.cursor
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
def Enumerate(node):
|
||||
if node.kind == cindex.CursorKind.NAMESPACE:
|
||||
for child in node.get_children():
|
||||
Enumerate(child)
|
||||
|
||||
if node.kind == cindex.CursorKind.FUNCTION_DECL and node.location.file.name == input_filename:
|
||||
func = {}
|
||||
func["func_name"] = node.spelling
|
||||
func["raw_return_type"] = node.result_type.spelling
|
||||
func["simple_return_type"] = SimpleVarType(node.result_type.spelling)
|
||||
func["var_names"] = []
|
||||
func["raw_var_types"] = []
|
||||
func["simple_var_types"] = []
|
||||
for arg in node.get_arguments():
|
||||
func["var_names"].append(arg.displayname)
|
||||
func["raw_var_types"].append(arg.type.spelling)
|
||||
func["simple_var_types"].append(SimpleVarType(arg.type.spelling))
|
||||
funcs_list.append(func)
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
for child in cursor.get_children():
|
||||
Enumerate(child)
|
||||
|
||||
return funcs_list
|
||||
# ----------------------------------------------------------------------
|
|
@ -0,0 +1,65 @@
|
|||
'''Integration tests for CppToJson.py
|
||||
'''
|
||||
import sys
|
||||
import os
|
||||
import json
|
||||
import unittest
|
||||
import CommonEnvironment
|
||||
|
||||
from DataPipelines import CppToJson
|
||||
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
_script_fullpath = CommonEnvironment.ThisFullpath()
|
||||
_script_dir, _script_name = os.path.split(_script_fullpath)
|
||||
# ----------------------------------------------------------------------
|
||||
|
||||
|
||||
class FileTest(unittest.TestCase):
|
||||
'''
|
||||
The purpose of this function is to verify the file-based capabilities of the ObtainFunctions method. It will make sure
|
||||
that the files are being opened and the information inside is being correctly processed.
|
||||
'''
|
||||
def test_basic_file(self):
|
||||
func_list = CppToJson.ObtainFunctions(os.path.join(_script_dir, "basicFunc.cpp"))
|
||||
|
||||
self.assertEqual(func_list[0], {'func_name': 'add', 'raw_return_type': 'int', 'simple_return_type': 'int', 'var_names': ['a', 'b'], 'raw_var_types': ['int', 'int'], 'simple_var_types': ['int', 'int']})
|
||||
self.assertEqual(func_list[1], {'func_name': 'sub', 'raw_return_type': 'float', 'simple_return_type': 'float', 'var_names': ['a', 'b'], 'raw_var_types': ['float', 'float'], 'simple_var_types': ['float', 'float']})
|
||||
self.assertEqual(func_list[2], {'func_name': 'isPos', 'raw_return_type': 'bool', 'simple_return_type': 'bool', 'var_names': ['x'], 'raw_var_types': ['bool'], 'simple_var_types': ['bool']})
|
||||
self.assertEqual(func_list[3], {'func_name': 'three', 'raw_return_type': 'int', 'simple_return_type': 'int', 'var_names': [], 'raw_var_types': [], 'simple_var_types': []})
|
||||
self.assertEqual(func_list[4], {'func_name': 'nothing', 'raw_return_type': 'void', 'simple_return_type': 'void', 'var_names': [], 'raw_var_types': [], 'simple_var_types': []})
|
||||
self.assertEqual(func_list[5], {'func_name': 'main', 'raw_return_type': 'int', 'simple_return_type': 'int', 'var_names': [], 'raw_var_types': [], 'simple_var_types': []})
|
||||
|
||||
def test_medium_file(self):
|
||||
func_list = CppToJson.ObtainFunctions(os.path.join(_script_dir, "mediumFunc.cpp"))
|
||||
|
||||
self.assertEqual(func_list[0], {'func_name': 'add', 'raw_return_type': 'int', 'simple_return_type': 'int', 'var_names': ['a', 'b'], 'raw_var_types': ['float', 'int'], 'simple_var_types': ['float', 'int']})
|
||||
self.assertEqual(func_list[1], {'func_name': 'mult', 'raw_return_type': 'float', 'simple_return_type': 'float', 'var_names': ['a', 'b', 'signal'], 'raw_var_types': ['int', 'float', 'bool'], 'simple_var_types': ['int', 'float', 'bool']})
|
||||
self.assertEqual(func_list[2], {'func_name': 'toUp', 'raw_return_type': 'std::string', 'simple_return_type': 'std::string', 'var_names': ['s'], 'raw_var_types': ['std::string'], 'simple_var_types': ['std::string']})
|
||||
self.assertEqual(func_list[3], {'func_name': 'fat', 'raw_return_type': 'int', 'simple_return_type': 'int', 'var_names': ['curr', 'at'], 'raw_var_types': ['int', 'int'], 'simple_var_types': ['int', 'int']})
|
||||
self.assertEqual(func_list[4], {'func_name': 'main', 'raw_return_type': 'int', 'simple_return_type': 'int', 'var_names': [], 'raw_var_types': [], 'simple_var_types': []})
|
||||
|
||||
|
||||
def test_hard_file(self):
|
||||
func_list = CppToJson.ObtainFunctions(os.path.join(_script_dir, "hardFunc.cpp"))
|
||||
|
||||
self.assertEqual(func_list[0], {'func_name': 'add', 'raw_return_type': 'int', 'simple_return_type': 'int', 'var_names': ['a'], 'raw_var_types': ['int'], 'simple_var_types': ['int']})
|
||||
self.assertEqual(func_list[1], {'func_name': 'main', 'raw_return_type': 'int', 'simple_return_type': 'int', 'var_names': [], 'raw_var_types': [], 'simple_var_types': []})
|
||||
self.assertEqual(func_list[2], {'func_name': 'bubbleSort', 'raw_return_type': 'vector<int>', 'simple_return_type': 'vector<int>', 'var_names': ['v'], 'raw_var_types': ['vector<int>'], 'simple_var_types': ['vector<int>']})
|
||||
self.assertEqual(func_list[3], {'func_name': 'sizeOfMap', 'raw_return_type': 'int', 'simple_return_type': 'int', 'var_names': ['mp'], 'raw_var_types': ['map<int, bool>'], 'simple_var_types': ['map<int, bool>']})
|
||||
self.assertEqual(func_list[4], {'func_name': 'keys', 'raw_return_type': 'vector<int>', 'simple_return_type': 'vector<int>', 'var_names': ['mp'], 'raw_var_types': ['map<int, int>'], 'simple_var_types': ['map<int, int>']})
|
||||
self.assertEqual(func_list[5], {'func_name': 'goCount', 'raw_return_type': 'map<float, int>', 'simple_return_type': 'map<float, int>', 'var_names': ['v', 'signal'], 'raw_var_types': ['vector<float>', 'bool'], 'simple_var_types': ['vector<float>', 'bool']})
|
||||
|
||||
|
||||
def test_convoluted_file(self):
|
||||
func_list = CppToJson.ObtainFunctions(os.path.join(_script_dir, "convolutedFunc.cpp"))
|
||||
|
||||
self.assertEqual(func_list[0], {'func_name': 'matrix', 'raw_return_type': 'vector<vector<int> >', 'simple_return_type': 'vector<vector<int> >', 'var_names': ['n'], 'raw_var_types': ['int'], 'simple_var_types': ['int']})
|
||||
self.assertEqual(func_list[1], {'func_name': 'nonsense', 'raw_return_type': 'map<map<int, vector<bool> >, vector<float> >', 'simple_return_type': 'map<map<int, vector<bool> >, vector<float> >', 'var_names': ['n'], 'raw_var_types': ['int'], 'simple_var_types': ['int']})
|
||||
self.assertEqual(func_list[2], {'func_name': 'vectorLine', 'raw_return_type': 'vector<vector<vector<vector<float> > > >', 'simple_return_type': 'vector<vector<vector<vector<float> > > >', 'var_names': ['mp'], 'raw_var_types': ['map<bool, int>'], 'simple_var_types': ['map<bool, int>']})
|
||||
self.assertEqual(func_list[3], {'func_name': 'countVector', 'raw_return_type': 'map<int, int>', 'simple_return_type': 'map<int, int>', 'var_names': ['v'], 'raw_var_types': ['vector<vector<int> >'], 'simple_var_types': ['vector<vector<int> >']})
|
||||
self.assertEqual(func_list[4], {'func_name': 'main', 'raw_return_type': 'int', 'simple_return_type': 'int', 'var_names': [], 'raw_var_types': [], 'simple_var_types': []})
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
|
@ -0,0 +1,30 @@
|
|||
#include <iostream>
|
||||
#include <stdio.h>
|
||||
|
||||
using namespace std;
|
||||
|
||||
int add(int a, int b){
|
||||
return a + b;
|
||||
}
|
||||
|
||||
float sub(float a, float b){
|
||||
return a + b;
|
||||
}
|
||||
|
||||
bool isPos(bool x){
|
||||
return x;
|
||||
}
|
||||
|
||||
int three(){
|
||||
return 3;
|
||||
}
|
||||
|
||||
void nothing(){
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
int main(){
|
||||
cout << "Hello World" << endl;
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,61 @@
|
|||
#include <iostream>
|
||||
#include <stdio.h>
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
using namespace std;
|
||||
|
||||
vector<vector<int>> matrix(int n){
|
||||
vector<vector<int>> ret(n);
|
||||
for(int i = 0; i < n; i++){
|
||||
for(int j = 0; j < n; j++){
|
||||
ret[i].push_back(i*4 + j);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
map<map<int, vector<bool>>, vector<float>> nonsense(int n){
|
||||
map<map<int, vector<bool>>, vector<float>> ret;
|
||||
map<int, vector<bool>> mpv;
|
||||
mpv[32].push_back(0);
|
||||
mpv[347].push_back(1);
|
||||
|
||||
ret[mpv].push_back(3.1415926);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
vector<vector<vector<vector<float>>>> vectorLine(map<bool, int> mp){
|
||||
vector<vector<vector<vector<float>>>> ret;
|
||||
vector<float> v = {3.4, 7.231321, 5, 0, -10};
|
||||
vector<vector<float>> vv = {v, v};
|
||||
vector<vector<vector<float>>> vvv = {vv, vv, vv, vv, vv};
|
||||
ret.push_back(vvv);
|
||||
vvv.clear();
|
||||
ret.push_back(vvv);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
map<int, int> countVector(vector<vector<int>> v){
|
||||
map<int, int>ret;
|
||||
for(int i = 0; i < v.size(); i++){
|
||||
ret[i] = v[i].size();
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int main(){
|
||||
cout << "Hello World" << endl;
|
||||
vector<vector<int>>v;
|
||||
v = matrix(4);
|
||||
for(int i=0; i<4; i++){
|
||||
for(int j=0; j<4; j++){
|
||||
cout << v[i][j] << " ";
|
||||
}
|
||||
cout << endl;
|
||||
}
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
#include <iostream>
|
||||
#include <stdio.h>
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
|
||||
using namespace std;
|
||||
|
||||
int add(int a){
|
||||
return 2;
|
||||
}
|
||||
|
||||
int n;
|
||||
vector<int>x;
|
||||
|
||||
int main(){
|
||||
cout << "Hello World" << endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
vector<int> bubbleSort(vector<int> v){
|
||||
for(int i = 0; i < v.size(); i++){
|
||||
for(int j = i + 1; j < v.size() ; j++){
|
||||
if(v[i] > v[j])
|
||||
swap(v[i], v[j]);
|
||||
}
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
int sizeOfMap(map<int, bool> mp){
|
||||
return mp.size();
|
||||
}
|
||||
vector<int> keys(map<int, int> mp){
|
||||
vector<int> ret;
|
||||
for(auto it : mp){
|
||||
ret.push_back(it.first);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
map<float, int> goCount(vector<float> v, bool signal){
|
||||
map<float, int> ret;
|
||||
for(int i = 0; i < v.size(); i++){
|
||||
ret[i] = v[i] * (2*signal - 1);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
#include <iostream>#include <stdio.h>#include <string>
|
||||
|
||||
using namespace std;
|
||||
|
||||
int add(float a, int b){
|
||||
return a + b;
|
||||
}
|
||||
|
||||
float mult(int a, float b, bool signal){
|
||||
return a * b * (2*signal - 1);
|
||||
}
|
||||
|
||||
string toUp(string s){
|
||||
if(s[0] <= 'a' and s[0]<='z')
|
||||
s[0] = s[0] - 'a' + 'A';
|
||||
return s;
|
||||
}
|
||||
|
||||
int fat(int curr, int at = 3){
|
||||
if(at == 0)return 1;
|
||||
return curr * fat(curr - 1, at - 1);
|
||||
}
|
||||
|
||||
int main(){
|
||||
cout << "Hello World" << endl;
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,135 @@
|
|||
'''Unit test for CppToJson.py
|
||||
'''
|
||||
import sys
|
||||
import json
|
||||
import unittest
|
||||
import textwrap
|
||||
|
||||
from DataPipelines import CppToJson
|
||||
|
||||
class FuncTest(unittest.TestCase):
|
||||
|
||||
def test_add_func(self):
|
||||
s = textwrap.dedent('''
|
||||
int add(int a, int b){
|
||||
return a+b;
|
||||
}
|
||||
int main(){
|
||||
return 0;
|
||||
}
|
||||
''')
|
||||
func_list = CppToJson.ObtainFunctions(s)
|
||||
|
||||
self.assertEqual(func_list[0]['func_name'], 'add')
|
||||
self.assertEqual(func_list[0]['raw_return_type'], 'int')
|
||||
self.assertEqual(func_list[0]['simple_return_type'], 'int')
|
||||
self.assertEqual(func_list[0]['var_names'], ['a', 'b'])
|
||||
self.assertEqual(func_list[0]['raw_var_types'], ['int', 'int'])
|
||||
self.assertEqual(func_list[0]['simple_var_types'], ['int', 'int'])
|
||||
|
||||
self.assertEqual(func_list[1]['func_name'], 'main')
|
||||
self.assertEqual(func_list[1]['raw_return_type'], 'int')
|
||||
self.assertEqual(func_list[1]['simple_return_type'], 'int')
|
||||
self.assertEqual(func_list[1]['var_names'], [])
|
||||
self.assertEqual(func_list[1]['raw_var_types'], [])
|
||||
self.assertEqual(func_list[1]['simple_var_types'], [])
|
||||
|
||||
def test_vector_func(self):
|
||||
s = textwrap.dedent('''
|
||||
#include <vector>
|
||||
std::vector<int> counting(std::vector<float> v, float x){
|
||||
std::vector<int>ret;
|
||||
for(int i = 0; i < v.size(); i++){
|
||||
if(v[i]==x)
|
||||
ret.push_back(i);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
int main(){
|
||||
return 0;
|
||||
}
|
||||
''')
|
||||
func_list = CppToJson.ObtainFunctions(s)
|
||||
|
||||
self.assertEqual(func_list[0]['func_name'], 'counting')
|
||||
self.assertEqual(func_list[0]['raw_return_type'], 'std::vector<int>')
|
||||
self.assertEqual(func_list[0]['simple_return_type'], 'std::vector<int>')
|
||||
self.assertEqual(func_list[0]['var_names'], ['v', 'x'])
|
||||
self.assertEqual(func_list[0]['raw_var_types'], ['std::vector<float>', 'float'])
|
||||
self.assertEqual(func_list[0]['simple_var_types'], ['std::vector<float>', 'float'])
|
||||
|
||||
self.assertEqual(func_list[1]['func_name'], 'main')
|
||||
self.assertEqual(func_list[1]['raw_return_type'], 'int')
|
||||
self.assertEqual(func_list[1]['simple_return_type'], 'int')
|
||||
self.assertEqual(func_list[1]['var_names'], [])
|
||||
self.assertEqual(func_list[1]['raw_var_types'], [])
|
||||
self.assertEqual(func_list[1]['simple_var_types'], [])
|
||||
|
||||
|
||||
def test_vector_using_std_func(self):
|
||||
s = textwrap.dedent('''
|
||||
#include <vector>
|
||||
using namespace std;
|
||||
vector<int> counting(vector<float> v, float x){
|
||||
vector<int>ret;for(int i = 0; i < v.size(); i++){
|
||||
if(v[i]==x)
|
||||
ret.push_back(i);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
int main(){
|
||||
return 0;
|
||||
}
|
||||
''')
|
||||
func_list = CppToJson.ObtainFunctions(s)
|
||||
|
||||
self.assertEqual(func_list[0]['func_name'], 'counting')
|
||||
self.assertEqual(func_list[0]['raw_return_type'], 'vector<int>')
|
||||
self.assertEqual(func_list[0]['simple_return_type'], 'vector<int>')
|
||||
self.assertEqual(func_list[0]['var_names'], ['v', 'x'])
|
||||
self.assertEqual(func_list[0]['raw_var_types'], ['vector<float>', 'float'])
|
||||
self.assertEqual(func_list[0]['simple_var_types'], ['vector<float>', 'float'])
|
||||
|
||||
self.assertEqual(func_list[1]['func_name'], 'main')
|
||||
self.assertEqual(func_list[1]['raw_return_type'], 'int')
|
||||
self.assertEqual(func_list[1]['simple_return_type'], 'int')
|
||||
self.assertEqual(func_list[1]['var_names'], [])
|
||||
self.assertEqual(func_list[1]['raw_var_types'], [])
|
||||
self.assertEqual(func_list[1]['simple_var_types'], [])
|
||||
|
||||
|
||||
def test_vector_map(self):
|
||||
s = textwrap.dedent('''
|
||||
#include <vector>
|
||||
#include <map>
|
||||
using namespace std;
|
||||
vector<vector<int>> counting(vector<map<float,int>> v, float x){
|
||||
vector<vector<int>>ret;
|
||||
for(int i=0; i<v.size(); i++){
|
||||
if(v[i][x])ret.push_back({1, 2, 3, 4});
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
int main(){
|
||||
return 0;
|
||||
}
|
||||
''')
|
||||
func_list = CppToJson.ObtainFunctions(s)
|
||||
|
||||
self.assertEqual(func_list[0]['func_name'], 'counting')
|
||||
self.assertEqual(func_list[0]['raw_return_type'], 'vector<vector<int> >')
|
||||
self.assertEqual(func_list[0]['simple_return_type'], 'vector<vector<int> >')
|
||||
self.assertEqual(func_list[0]['var_names'], ['v', 'x'])
|
||||
self.assertEqual(func_list[0]['raw_var_types'], ['vector<map<float, int> >', 'float'])
|
||||
self.assertEqual(func_list[0]['simple_var_types'], ['vector<map<float, int> >', 'float'])
|
||||
|
||||
self.assertEqual(func_list[1]['func_name'], 'main')
|
||||
self.assertEqual(func_list[1]['raw_return_type'], 'int')
|
||||
self.assertEqual(func_list[1]['simple_return_type'], 'int')
|
||||
self.assertEqual(func_list[1]['var_names'], [])
|
||||
self.assertEqual(func_list[1]['raw_var_types'], [])
|
||||
self.assertEqual(func_list[1]['simple_var_types'], [])
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
|
@ -0,0 +1,24 @@
|
|||
import sys
|
||||
import json
|
||||
from DataPipelines import CppToJson
|
||||
|
||||
from CommonEnvironment import CommandLine
|
||||
|
||||
@CommandLine.EntryPoint
|
||||
@CommandLine.Constraints(
|
||||
input_filename=CommandLine.FilenameTypeInfo(
|
||||
arity="+",
|
||||
),
|
||||
)
|
||||
def EntryPoint(
|
||||
input_filename,
|
||||
):
|
||||
file_dict = {}
|
||||
for file_name in input_filename:
|
||||
file_dict[file_name] = CppToJson.ObtainFunctions(file_name)
|
||||
sys.stdout.write("{}\n".format(json.dumps(file_dict)))
|
||||
return 0
|
||||
|
||||
if __name__ == "__main__":
|
||||
try: sys.exit(CommandLine.Main())
|
||||
except KeyboardInterrupt: pass
|
Загрузка…
Ссылка в новой задаче