-
Notifications
You must be signed in to change notification settings - Fork 581
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
CLOCBear: Add CLOCBear #1691
base: master
Are you sure you want to change the base?
CLOCBear: Add CLOCBear #1691
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -25,6 +25,7 @@ addons: | |
- cabal-install-1.24 | ||
- chktex | ||
- clang-3.4 | ||
- cloc | ||
- cppcheck | ||
- devscripts | ||
- flawfinder | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
import re | ||
|
||
from coalib.bearlib.abstractions.Linter import linter | ||
from coalib.bears.GlobalBear import GlobalBear | ||
from coalib.results.Result import Result | ||
from coalib.results.RESULT_SEVERITY import RESULT_SEVERITY | ||
from dependency_management.requirements.DistributionRequirement import ( | ||
DistributionRequirement) | ||
|
||
|
||
@linter(executable='cloc') | ||
class CLOCBear(GlobalBear): | ||
""" | ||
Summarises a file or number of files in directory structure | ||
with total lines, number of comment lines, number of actual code lines | ||
using CLI tool cloc | ||
""" | ||
LANGUAGES = {'All'} | ||
REQUIREMENTS = {DistributionRequirement('cloc')} | ||
AUTHORS = {'The coala developers'} | ||
AUTHORS_EMAILS = {'[email protected]'} | ||
LICENSE = 'AGPL-3.0' | ||
CAN_DETECT = {'Statistics'} | ||
SEE_MORE = 'https://github.com/AlDanial/cloc' | ||
|
||
@staticmethod | ||
def create_arguments(filename, file, config_file): | ||
return ('--csv', filename) | ||
|
||
def process_output(self, output, filename, file): | ||
lines = output.split('\n') | ||
regex = r'(\d+).*?\n\s+(\d+)' | ||
files, ignored_files = re.search( | ||
regex, '\n'.join(lines[1:3]), re.MULTILINE).group(1, 2) | ||
if files == ignored_files: | ||
msg = 'File does not belong to valid programming language.' | ||
yield Result.from_values(origin=self, | ||
message=msg, | ||
file=filename, | ||
severity=RESULT_SEVERITY.MAJOR) | ||
else: | ||
regex = re.compile(r'(\d+),(\S+),(\d+),(\d+),(\d+)') | ||
# cloc tool gives summary of files | ||
# starting from 5th(0-index) line up to second last line | ||
for row in lines[5:-1]: | ||
match = regex.match(row) | ||
|
||
nfiles, lang = match.group(1, 2) | ||
blank, comment, code = map(int, match.group(3, 4, 5)) | ||
total = blank + comment + code | ||
|
||
report = '\n'.join(['Language: {0}'.format(lang), | ||
'Total files: {0}'.format(nfiles), | ||
'Total lines: {0}'.format(total), | ||
'Code lines: {0} ({1:.2f}%)'.format( | ||
code, code * 100.0 / total), | ||
'Comment lines: {0} ({1:.2f}%)'.format( | ||
comment, comment * 100.0 / total), | ||
'Blank lines: {0} ({1:.2f}%)'.format( | ||
blank, blank * 100.0 / total) | ||
]) | ||
yield Result.from_values(origin=self, | ||
message=report, | ||
file=filename, | ||
severity=RESULT_SEVERITY.INFO) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
import os | ||
from queue import Queue | ||
|
||
from coalib.settings.Section import Section | ||
from coalib.testing.LocalBearTestHelper import LocalBearTestHelper | ||
from coalib.testing.BearTestHelper import generate_skip_decorator | ||
from coalib.results.RESULT_SEVERITY import RESULT_SEVERITY | ||
from coalib.results.Result import Result | ||
|
||
from bears.general.CLOCBear import CLOCBear | ||
|
||
|
||
def get_absolute_test_path(file): | ||
return os.path.join(os.path.dirname(__file__), | ||
'cloc_test_files', file) | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The code does not comply to PEP8. PEP8Bear, severity NORMAL, section The issue can be fixed by applying the following patch: --- a/tests/general/CLOCBearTest.py
+++ b/tests/general/CLOCBearTest.py
@@ -13,8 +13,10 @@
return os.path.join(os.path.dirname(__file__),
'cloc_test_files', file)
+
def load_testfile(name):
return open(get_absolute_test_path(name)).readlines()
+
@generate_skip_decorator(CLOCBear)
class CLOCBearTest(LocalBearTestHelper): |
||
|
||
def load_testfile(name): | ||
with open(get_absolute_test_path(name)) as file: | ||
return file.readlines() | ||
|
||
|
||
@generate_skip_decorator(CLOCBear) | ||
class CLOCBearTest(LocalBearTestHelper): | ||
|
||
def setUp(self): | ||
self.uut = CLOCBear(Section('name'), Queue()) | ||
self.test_files = ['example1.cpp', 'example2.py', | ||
'example3.cpp', 'example4.txt'] | ||
self.expected_results = {self.test_files[0]: {'LANGUAGE': 'C++', | ||
'FILES': 1, | ||
'CODE': 6, | ||
'COMMENTS': 5, | ||
'BLANK': 3}, | ||
self.test_files[1]: {'LANGUAGE': 'Python', | ||
'FILES': 1, | ||
'CODE': 3, | ||
'COMMENTS': 2, | ||
'BLANK': 2}, | ||
self.test_files[2]: {'LANGUAGE': 'C++', | ||
'FILES': 1, | ||
'CODE': 11, | ||
'COMMENTS': 0, | ||
'BLANK': 3}, | ||
self.test_files[3]: 'File does not belong ' | ||
'to valid programming ' | ||
'language.' | ||
} | ||
|
||
def build_message(self, filename): | ||
result = self.expected_results[filename] | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. newline |
||
|
||
lang = result['LANGUAGE'] | ||
nfiles = result['FILES'] | ||
code = result['CODE'] | ||
comment = result['COMMENTS'] | ||
blank = result['BLANK'] | ||
total = code + comment + blank | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. newline after this |
||
|
||
message = '\n'.join(['Language: {0}'.format(lang), | ||
'Total files: {0}'.format(nfiles), | ||
'Total lines: {0}'.format(total), | ||
'Code lines: {0} ({1:.2f}%)'.format( | ||
code, code * 100.0 / total), | ||
'Comment lines: {0} ({1:.2f}%)'.format( | ||
comment, comment * 100.0 / total), | ||
'Blank lines: {0} ({1:.2f}%)'.format( | ||
blank, blank * 100.0 / total) | ||
]) | ||
return message | ||
|
||
def test_valid(self): | ||
for filename in self.test_files[:-1]: | ||
file_contents = load_testfile(filename) | ||
self.check_results( | ||
self.uut, | ||
file_contents, | ||
[Result.from_values('CLOCBear', | ||
self.build_message(filename), | ||
file=get_absolute_test_path(filename), | ||
severity=RESULT_SEVERITY.INFO)], | ||
filename=get_absolute_test_path(filename)) | ||
|
||
def test_invalid(self): | ||
filename = self.test_files[3] | ||
file_contents = load_testfile(filename) | ||
self.check_results( | ||
self.uut, | ||
file_contents, | ||
[Result.from_values('CLOCBear', | ||
str(self.expected_results[filename]), | ||
file=get_absolute_test_path(filename), | ||
severity=RESULT_SEVERITY.MAJOR)], | ||
filename=get_absolute_test_path(filename)) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
// This comments are for testing purpose. | ||
|
||
/* | ||
Just like any other programmer, | ||
This example file will also try to print only two words | ||
*/ | ||
|
||
#include <cstdio> | ||
|
||
int main() | ||
{ | ||
std::cout << 'Hello World!' << std::endl; | ||
return 0; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
# This comments are for testing purpose | ||
# This program will just try to add two static numbers | ||
|
||
first = 5 # First number | ||
second = 10 # Second number | ||
|
||
sum = first + second |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
#include <cstdio> | ||
|
||
#define PI 3.1415926 | ||
using namespace std; | ||
|
||
|
||
int main() | ||
{ | ||
const double radii = 1.0; | ||
const double area = PI * radii * radii; | ||
cout << 'Area for the circle with radii ' << radii << | ||
' is ' << area << endl; | ||
return 0; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
This is normal text file. And it is not specific to any programming language. | ||
So, this has to detected as invalid file by cloc. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Any reason to leave this line ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Its been added by coala itself, through
PycodestyleBear
.Message received on running coala:
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That is two lines after the imports, before the
def
. It is a PEP8 rule.But a blank line between
coalib
andbears
imports is OK.