Пример #1
0
def parse_functions(main_cpp_name, main_cpp_path, silent=False):
    p = subprocess.Popen(
        "clang-check -ast-dump %s --extra-arg='-fno-color-diagnostics' --" %
        main_cpp_path,
        shell=True,
        stdout=subprocess.PIPE)
    main_cpp_found = False
    functions = {}

    if not silent:
        print('parsing function declarations:')
    while p.poll() is None:
        line = p.stdout.readline().decode('utf-8')
        if main_cpp_name in line:
            main_cpp_found = True
        if main_cpp_found and 'FunctionDecl' in line and 'line' in line:
            line = line.strip()
            func_decl = FunctionDeclaration(line)
            if not func_decl.error:
                func_prototype = str(func_decl)
                if not silent:
                    print('[line %d-%d] %s' %
                          (func_decl.start, func_decl.end, func_decl))
                if func_prototype not in functions:
                    functions[func_prototype] = Function(func_decl)
                else:
                    functions[func_prototype].add_declaration(func_decl)
            elif not silent:
                print('error occurred in %s', line)

    if not silent:
        print('\nparsing cpp file:')

    main_cpp_contents = read_file(main_cpp_path, silent=silent)

    for i, func_decl in enumerate(FunctionDeclaration.function_declares):
        if func_decl.end <= len(main_cpp_contents):
            if i > 1:
                start = max(
                    FunctionDeclaration.get_by_id(i - 1).end,
                    func_decl.start - 20)
            else:
                start = max(0, func_decl.start - 20)
            end = func_decl.end
            func_decl.set_body([(x, main_cpp_contents[x])
                                for x in range(start, end)])

    return functions
Пример #2
0
def parse_functions_new(project_dir, files, silent=False, functions=None):
    if not functions:
        functions = dict()

    split_sources_headers(files)
    sources, headers, _ = split_sources_headers(files)
    files = sources + headers
    sources_path = build_full_paths(project_dir, sources)
    files_path = build_full_paths(project_dir, files)
    p = subprocess.Popen(
        "clang-check -ast-dump %s --extra-arg='-fno-color-diagnostics' --" %
        ' '.join(sources_path),
        shell=True,
        stdout=subprocess.PIPE,
        stderr=silent and subprocess.PIPE or None)
    # print(sources_path)

    current_file = None

    if not silent:
        print('parsing function declarations:')

    func_decl_lines = []

    while p.poll() is None:
        line = p.stdout.readline().decode('utf-8').strip()
        result = re.findall(r'<(?!(line|col))(.*?), (line|col):.*?>', line)
        if result:
            file_name = result[0][1]
            flag = False
            for i, file_path in enumerate(files_path):
                if file_path in file_name:
                    # print(files[i], line)
                    current_file = files[i]
                    flag = True
                    break
            if not flag:
                current_file = None

        if current_file and 'line' in line and ' default ' not in line and \
                ('FunctionDecl' in line or 'CXXConstructorDecl' in line
                 or 'CXXDestructorDecl' in line or 'CXXMethodDecl' in line):
            # print(line)
            line = line.strip()
            func_decl_lines.append((line, current_file))

    file_func_decls = {x: [] for x in files}

    for line, file in func_decl_lines:
        func_decl = FunctionDeclaration(line, file)
        if not func_decl.error:
            func_prototype = str(func_decl)
            if not silent:
                print('[%s:%d-%d] %s' % (func_decl.file, func_decl.start,
                                         func_decl.end, func_decl))
            if func_prototype not in functions:
                functions[func_prototype] = Function(func_decl)
            else:
                functions[func_prototype].add_declaration(func_decl)
            file_func_decls[file].append(func_decl)
        elif not silent:
            print('error occurred in %s' % line)

    if not silent:
        print('\nparsing cpp files:')

    for i, file in enumerate(files):
        try:
            file_contents = read_file(files_path[i], silent=silent)
            func_decls = sorted(file_func_decls[file], key=lambda x: x.start)
            for j, func_decl in enumerate(func_decls):
                if func_decl.end <= len(file_contents):
                    # print(j, func_decl)
                    if j > 0:
                        start = max(func_decls[j - 1].end,
                                    func_decl.start - 20)
                    else:
                        start = max(0, func_decl.start - 20)
                    end = min(func_decl.end, len(file_contents) - 1)
                    func_decl.calculate_length(
                        file_contents[func_decl.start:end + 1])
                    func_decl.set_body([(x, file_contents[x])
                                        for x in range(start, end + 1)])
        except Exception as e:
            if not silent:
                print(e.args)

    for function in functions.values():
        function.calculate_length()

    return functions
Пример #3
0
def main(project_dir, silent=False):
    main_cpp_name = 'p2.cpp'
    main_cpp_path = os.path.join(project_dir, main_cpp_name)
    main_cpp_found = False
    functions = {}
    clang_check_score = 6

    p = subprocess.Popen("clang-check -ast-dump %s --" % main_cpp_path,
                         shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)

    if not silent:
        print('parsing function declarations:')
    while p.poll() is None:
        line = p.stdout.readline().decode('utf-8')
        if main_cpp_name in line:
            main_cpp_found = True
        if main_cpp_found and 'FunctionDecl' in line and 'line' in line:
            line = re.sub(r'\x1b(\[.*?[@-~]|\].*?(\x07|\x1b\\))', '', line).strip()
            func_decl = FunctionDeclaration(line)
            if not func_decl.error:
                func_prototype = str(func_decl)
                if not silent:
                    print('[line %d-%d] %s' % (func_decl.start, func_decl.end, func_decl))
                if func_prototype not in functions:
                    functions[func_prototype] = Function(func_decl)
                else:
                    functions[func_prototype].add_declaration(func_decl)
            elif not silent:
                print('error occurred in %s', line)

    if not silent:
        print('\nparsing cpp file:')
    main_cpp_contents = read_file(main_cpp_path, silent=silent)
    for i, func_decl in enumerate(FunctionDeclaration.function_declares):
        if func_decl.end <= len(main_cpp_contents):
            if i > 1:
                start = max(FunctionDeclaration.get_by_id(i - 1).end, func_decl.start - 5)
            else:
                start = max(0, func_decl.start - 5)
            end = func_decl.end
            func_decl.set_body([(x, main_cpp_contents[x]) for x in range(start, end)])

    if not silent:
        print('\ncounting function lines:')

    for func_prototype, func in functions.items():
        if not silent:
            print(func)
            line_count = func.count_lines()
            print('total lines: %d' % line_count)
            if line_count > 50 and clang_check_score > 0:
                clang_check_score -= 1

    if not silent:
        print('\nclang-check score: %d' % clang_check_score)

    clang_tidy_warnings = {}
    clang_tidy_warnings_count = 0
    clang_tidy_score = 0
    p = subprocess.Popen("clang-tidy %s -checks=-*,misc-*,performance-*,clang-analyzer-*,"
                         "readability-function-size,readability-identifier-naming,readability-named-parameter,"
                         "readability-redundant-*,readability-simplify-boolean-expr,readability-mis*,"
                         "--extra-arg='-fno-color-diagnostics' --"
                         % main_cpp_path, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)

    if not silent:
        print('\nparsing clang-tidy results:')
    while p.poll() is None:
        line = p.stdout.readline().decode('utf-8')
        line = re.sub(r'\x1b(\[.*?[@-~]|\].*?(\x07|\x1b\\))', '', line).strip()
        res = re.findall(r'warning:.*?\[(.*?)\]', line)
        if res:
            if res[0] in clang_tidy_warnings:
                clang_tidy_warnings[res[0]] += 1
            else:
                clang_tidy_warnings[res[0]] = 1
            clang_tidy_warnings_count += 1
    if clang_tidy_warnings_count <= 10:
        clang_tidy_score += 2
    elif clang_tidy_warnings_count <= 25:
        clang_tidy_score += 1
    if len(clang_tidy_warnings) <= 3:
        clang_tidy_score += 2
    elif len(clang_tidy_warnings) <= 6:
        clang_tidy_score += 1
    if not silent:
        pprint(clang_tidy_warnings)
        print('\nclang-tidy score: %d' % clang_tidy_score)

    if silent:
        print('%d,%d' % (clang_check_score, clang_tidy_score))