From 2995781ed7db6749048d56e41063fcdc24113ccc Mon Sep 17 00:00:00 2001 From: Rob van der Leek <5324924+robvanderleek@users.noreply.github.com> Date: Thu, 16 Jan 2025 22:03:06 +0100 Subject: [PATCH 1/4] =?UTF-8?q?refactor:=20=E2=99=BB=EF=B8=8F=20Refactor?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- codelimit/commands/check.py | 12 ++++++------ codelimit/common/Language.py | 8 ++++++-- codelimit/common/Scanner.py | 5 ++--- codelimit/languages/Cpp.py | 2 +- codelimit/languages/__init__.py | 9 --------- 5 files changed, 15 insertions(+), 21 deletions(-) diff --git a/codelimit/commands/check.py b/codelimit/commands/check.py index f0d7318..89c7fa4 100644 --- a/codelimit/commands/check.py +++ b/codelimit/commands/check.py @@ -7,9 +7,9 @@ from pygments.util import ClassNotFound from codelimit.common.CheckResult import CheckResult +from codelimit.common.Language import Language from codelimit.common.Scanner import is_excluded, scan_file, generate_exclude_spec from codelimit.common.lexer_utils import lex -from codelimit.languages import Languages def check_command(paths: list[Path], quiet: bool): @@ -30,9 +30,9 @@ def check_command(paths: list[Path], quiet: bool): check_file(abs_path, check_result) exit_code = 1 if check_result.unmaintainable > 0 else 0 if ( - not quiet - or check_result.hard_to_maintain > 0 - or check_result.unmaintainable > 0 + not quiet + or check_result.hard_to_maintain > 0 + or check_result.unmaintainable > 0 ): check_result.report() raise typer.Exit(code=exit_code) @@ -56,11 +56,11 @@ def check_file(path: Path, check_result: CheckResult): except ClassNotFound: return lexer_name = lexer.__class__.name - if lexer_name in Languages.by_name.keys(): + if lexer_name in Language.by_name.keys(): with open(path) as f: code = f.read() tokens = lex(lexer, code, False) - lexer_name = Languages.by_name[lexer.__class__.name] + lexer_name = Language.by_name[lexer.__class__.name] if lexer_name: measurements = scan_file(tokens, lexer_name) risks = sorted( diff --git a/codelimit/common/Language.py b/codelimit/common/Language.py index 2029ae3..2a9998b 100644 --- a/codelimit/common/Language.py +++ b/codelimit/common/Language.py @@ -1,15 +1,18 @@ -from abc import ABC, abstractmethod +from __future__ import annotations +from abc import ABC, abstractmethod from codelimit.common.Token import Token from codelimit.common.TokenRange import TokenRange from codelimit.common.scope.Header import Header class Language(ABC): + by_name: dict[str, Language] = {} def __init__(self, name: str, allow_nested_functions=True): self.name = name self.allow_nested_functions = allow_nested_functions + Language.by_name[name] = self @abstractmethod def extract_headers(self, tokens: list[Token]) -> list[Header]: @@ -17,6 +20,7 @@ def extract_headers(self, tokens: list[Token]) -> list[Header]: @abstractmethod def extract_blocks( - self, tokens: list[Token], headers: list[Header] + self, tokens: list[Token], headers: list[Header] ) -> list[TokenRange]: pass + diff --git a/codelimit/common/Scanner.py b/codelimit/common/Scanner.py index 1eda8e0..66681cb 100644 --- a/codelimit/common/Scanner.py +++ b/codelimit/common/Scanner.py @@ -28,7 +28,6 @@ from codelimit.common.utils import ( calculate_checksum, ) -from codelimit.languages import Languages locale.setlocale(locale.LC_ALL, "") @@ -70,7 +69,7 @@ def scan_path(path: Path, cached_report: Union[Report, None] = None, lexer = get_lexer_for_filename(rel_path) lexer_name = lexer.__class__.name file_path = os.path.join(root, file) - languages = Languages.by_name.keys() + languages = Language.by_name.keys() if lexer_name in languages: file_entry = _scan_file( result, lexer, path, file_path, cached_report @@ -126,7 +125,7 @@ def _analyze_file(path, rel_path, checksum, lexer): code = _read_file(path) all_tokens = lex(lexer, code, False) language_name = lexer.__class__.name - language = Languages.by_name[language_name] + language = Language.by_name[language_name] if language: measurements = scan_file(all_tokens, language) else: diff --git a/codelimit/languages/Cpp.py b/codelimit/languages/Cpp.py index e8a4f62..7fab1ba 100644 --- a/codelimit/languages/Cpp.py +++ b/codelimit/languages/Cpp.py @@ -17,6 +17,6 @@ def extract_headers(self, tokens: list[Token]) -> list[Header]: return get_headers(tokens, [Name(), OneOrMore(Balanced("(", ")"))], Symbol("{")) def extract_blocks( - self, tokens: list[Token], headers: list[Header] + self, tokens: list[Token], headers: list[Header] ) -> list[TokenRange]: return get_blocks(tokens, "{", "}") diff --git a/codelimit/languages/__init__.py b/codelimit/languages/__init__.py index 1c70853..33f5087 100644 --- a/codelimit/languages/__init__.py +++ b/codelimit/languages/__init__.py @@ -13,12 +13,3 @@ class Languages: JavaScript = JavaScript() Python = Python() TypeScript = TypeScript() - - by_name = { - C.name: C, - Cpp.name: Cpp, - Java.name: Java, - JavaScript.name: JavaScript, - Python.name: Python, - TypeScript.name: TypeScript, - } From 94fa979c380a921acda849656233ad2bd281404a Mon Sep 17 00:00:00 2001 From: Rob van der Leek <5324924+robvanderleek@users.noreply.github.com> Date: Fri, 17 Jan 2025 22:16:23 +0100 Subject: [PATCH 2/4] =?UTF-8?q?feat:=20=E2=9C=A8=20Support=20C#?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- codelimit/commands/check.py | 6 ++-- codelimit/common/Language.py | 4 +-- codelimit/common/Scanner.py | 5 +-- .../token_matching/predicate/TokenValue.py | 2 +- codelimit/languages/CSharp.py | 20 +++++++++++ codelimit/languages/TypeScript.py | 4 ++- codelimit/languages/__init__.py | 12 +++---- .../token_matching/test_TokenMatching.py | 13 +++++++ tests/conftest.py | 12 +++---- tests/languages/test_C.py | 20 +++++------ tests/languages/test_CSharp.py | 31 ++++++++++++++++ tests/languages/test_Cpp.py | 16 ++++----- tests/languages/test_Java.py | 23 ++++++------ tests/languages/test_JavaScript.py | 17 ++++----- tests/languages/test_Python.py | 35 +++++++++---------- tests/languages/test_TypeScript.py | 10 +++--- 16 files changed, 147 insertions(+), 83 deletions(-) create mode 100644 codelimit/languages/CSharp.py create mode 100644 tests/languages/test_CSharp.py diff --git a/codelimit/commands/check.py b/codelimit/commands/check.py index 89c7fa4..481214b 100644 --- a/codelimit/commands/check.py +++ b/codelimit/commands/check.py @@ -7,9 +7,9 @@ from pygments.util import ClassNotFound from codelimit.common.CheckResult import CheckResult -from codelimit.common.Language import Language from codelimit.common.Scanner import is_excluded, scan_file, generate_exclude_spec from codelimit.common.lexer_utils import lex +from codelimit.languages import Languages def check_command(paths: list[Path], quiet: bool): @@ -56,11 +56,11 @@ def check_file(path: Path, check_result: CheckResult): except ClassNotFound: return lexer_name = lexer.__class__.name - if lexer_name in Language.by_name.keys(): + if lexer_name in Languages.by_name.keys(): with open(path) as f: code = f.read() tokens = lex(lexer, code, False) - lexer_name = Language.by_name[lexer.__class__.name] + lexer_name = Languages.by_name[lexer.__class__.name] if lexer_name: measurements = scan_file(tokens, lexer_name) risks = sorted( diff --git a/codelimit/common/Language.py b/codelimit/common/Language.py index 2a9998b..98395bf 100644 --- a/codelimit/common/Language.py +++ b/codelimit/common/Language.py @@ -1,18 +1,17 @@ from __future__ import annotations from abc import ABC, abstractmethod + from codelimit.common.Token import Token from codelimit.common.TokenRange import TokenRange from codelimit.common.scope.Header import Header class Language(ABC): - by_name: dict[str, Language] = {} def __init__(self, name: str, allow_nested_functions=True): self.name = name self.allow_nested_functions = allow_nested_functions - Language.by_name[name] = self @abstractmethod def extract_headers(self, tokens: list[Token]) -> list[Header]: @@ -23,4 +22,3 @@ def extract_blocks( self, tokens: list[Token], headers: list[Header] ) -> list[TokenRange]: pass - diff --git a/codelimit/common/Scanner.py b/codelimit/common/Scanner.py index 66681cb..1eda8e0 100644 --- a/codelimit/common/Scanner.py +++ b/codelimit/common/Scanner.py @@ -28,6 +28,7 @@ from codelimit.common.utils import ( calculate_checksum, ) +from codelimit.languages import Languages locale.setlocale(locale.LC_ALL, "") @@ -69,7 +70,7 @@ def scan_path(path: Path, cached_report: Union[Report, None] = None, lexer = get_lexer_for_filename(rel_path) lexer_name = lexer.__class__.name file_path = os.path.join(root, file) - languages = Language.by_name.keys() + languages = Languages.by_name.keys() if lexer_name in languages: file_entry = _scan_file( result, lexer, path, file_path, cached_report @@ -125,7 +126,7 @@ def _analyze_file(path, rel_path, checksum, lexer): code = _read_file(path) all_tokens = lex(lexer, code, False) language_name = lexer.__class__.name - language = Language.by_name[language_name] + language = Languages.by_name[language_name] if language: measurements = scan_file(all_tokens, language) else: diff --git a/codelimit/common/token_matching/predicate/TokenValue.py b/codelimit/common/token_matching/predicate/TokenValue.py index e713beb..42c1526 100644 --- a/codelimit/common/token_matching/predicate/TokenValue.py +++ b/codelimit/common/token_matching/predicate/TokenValue.py @@ -22,4 +22,4 @@ def __hash__(self): return hash(self.value) def __str__(self): - return f"" + return self.value diff --git a/codelimit/languages/CSharp.py b/codelimit/languages/CSharp.py new file mode 100644 index 0000000..a943716 --- /dev/null +++ b/codelimit/languages/CSharp.py @@ -0,0 +1,20 @@ +from codelimit.common.Language import Language +from codelimit.common.gsm.operator.OneOrMore import OneOrMore +from codelimit.common.scope.scope_utils import ( + get_blocks, + get_headers, +) +from codelimit.common.token_matching.predicate.Balanced import Balanced +from codelimit.common.token_matching.predicate.Name import Name +from codelimit.common.token_matching.predicate.Symbol import Symbol + + +class CSharp(Language): + def __init__(self): + super().__init__('C#') + + def extract_headers(self, tokens: list) -> list: + return get_headers(tokens, [Name(), OneOrMore(Balanced('(', ')'))], Symbol('{')) + + def extract_blocks(self, tokens: list, headers: list) -> list: + return get_blocks(tokens, "{", "}") diff --git a/codelimit/languages/TypeScript.py b/codelimit/languages/TypeScript.py index 9fc8747..625d32e 100644 --- a/codelimit/languages/TypeScript.py +++ b/codelimit/languages/TypeScript.py @@ -14,8 +14,10 @@ class TypeScript(Language): + name = "TypeScript" + def __init__(self): - super().__init__("TypeScript") + super().__init__(self.name) def extract_headers(self, tokens: list[Token]) -> list[Header]: functions = get_headers( diff --git a/codelimit/languages/__init__.py b/codelimit/languages/__init__.py index 33f5087..a9976ff 100644 --- a/codelimit/languages/__init__.py +++ b/codelimit/languages/__init__.py @@ -1,4 +1,6 @@ +from codelimit.common.Language import Language from codelimit.languages.C import C +from codelimit.languages.CSharp import CSharp from codelimit.languages.Cpp import Cpp from codelimit.languages.Java import Java from codelimit.languages.JavaScript import JavaScript @@ -7,9 +9,7 @@ class Languages: - C = C() - Cpp = Cpp() - Java = Java() - JavaScript = JavaScript() - Python = Python() - TypeScript = TypeScript() + by_name: dict[str, Language] = {} + for subclass in Language.__subclasses__(): + language = subclass() + by_name[language.name] = language diff --git a/tests/common/token_matching/test_TokenMatching.py b/tests/common/token_matching/test_TokenMatching.py index ba26fb2..ae09406 100644 --- a/tests/common/token_matching/test_TokenMatching.py +++ b/tests/common/token_matching/test_TokenMatching.py @@ -1,4 +1,6 @@ +import pytest from pygments.lexers import PythonLexer +from pygments.lexers import CSharpLexer from codelimit.common.gsm.matcher import find_all from codelimit.common.gsm.operator.OneOrMore import OneOrMore @@ -6,6 +8,7 @@ from codelimit.common.token_matching.predicate.Balanced import Balanced from codelimit.common.token_matching.predicate.Keyword import Keyword from codelimit.common.token_matching.predicate.Name import Name +from codelimit.common.token_matching.predicate.Symbol import Symbol from codelimit.common.token_matching.predicate.TokenValue import TokenValue @@ -70,3 +73,13 @@ def test_ignore_incomplete_match(): result = find_all([Keyword("def"), Name(), OneOrMore(Balanced("(", ")"))], tokens) assert len(result) == 1 + + +@pytest.mark.skip +def test_predicate_follows_operator(): + code = "Split(new[] {' '})" + tokens = lex(CSharpLexer(), code) + + result = find_all([Name(), OneOrMore(Balanced("(", ")")), Symbol('{')], tokens) + + assert len(result) == 1 diff --git a/tests/conftest.py b/tests/conftest.py index f6dd945..c3fed14 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -8,20 +8,20 @@ from codelimit.common.source_utils import filter_tokens -def assert_units(code: str, language: Language, units: dict[str, int]): +def assert_functions(code: str, language: Language, functions: dict[str, int]): code = dedent(code).strip("\n") lexer = get_lexer_by_name(language.name) tokens = lex(lexer, code, False) code_tokens = filter_tokens(tokens) scopes = build_scopes(tokens, language) scopes = unfold_scopes(scopes) - assert len(scopes) == len(units) + assert len(scopes) == len(functions) for idx, scope in enumerate(scopes): - assert scope.header.name() in units - assert count_lines(scope, code_tokens) == units[scope.header.name()] + assert scope.header.name() in functions + assert count_lines(scope, code_tokens) == functions[scope.header.name()] -def print_units(code: str, language: Language): +def print_scopes(code: str, language: Language): code = dedent(code).strip("\n") lexer = get_lexer_by_name(language.name) tokens = lex(lexer, code, False) @@ -30,4 +30,4 @@ def print_units(code: str, language: Language): scopes = unfold_scopes(scopes) print() for scope in scopes: - print(f"{scope.header.name}: {count_lines(scope, code_tokens)}") + print(f"{scope.header.name()}: {count_lines(scope, code_tokens)}") diff --git a/tests/languages/test_C.py b/tests/languages/test_C.py index b99199a..766706e 100644 --- a/tests/languages/test_C.py +++ b/tests/languages/test_C.py @@ -1,5 +1,5 @@ -from codelimit.languages import Languages -from tests.conftest import assert_units +from codelimit.languages import C +from tests.conftest import assert_functions def test_simple_main_function(): @@ -9,7 +9,7 @@ def test_simple_main_function(): } """ - assert_units(code, Languages.C, {"main": 3}) + assert_functions(code, C(), {"main": 3}) def test_main_function_with_include(): @@ -21,7 +21,7 @@ def test_main_function_with_include(): } """ - assert_units(code, Languages.C, {"main": 4}) + assert_functions(code, C(), {"main": 4}) def test_simple_function(): @@ -32,7 +32,7 @@ def test_simple_function(): } """ - assert_units(code, Languages.C, {"bar": 3}) + assert_functions(code, C(), {"bar": 3}) def test_multiple_functions(): @@ -46,13 +46,13 @@ def test_multiple_functions(): } """ - assert_units(code, Languages.C, {"bar": 3, "foo": 3}) + assert_functions(code, C(), {"bar": 3, "foo": 3}) def test_no_functions(): code = "" - assert_units(code, Languages.C, {}) + assert_functions(code, C(), {}) def test_iteration_macro_is_not_a_function(): @@ -64,7 +64,7 @@ def test_iteration_macro_is_not_a_function(): } """ - assert_units(code, Languages.C, {"foo": 5}) + assert_functions(code, C(), {"foo": 5}) def test_formatting(): @@ -78,7 +78,7 @@ def test_formatting(): } """ - assert_units(code, Languages.C, {"nfs_register_sysctl": 7}) + assert_functions(code, C(), {"nfs_register_sysctl": 7}) def test_nested_header_but_no_body_inside_parent(): @@ -92,4 +92,4 @@ def test_nested_header_but_no_body_inside_parent(): }; """ - assert_units(code, Languages.C, {"foo": 5}) + assert_functions(code, C(), {"foo": 5}) diff --git a/tests/languages/test_CSharp.py b/tests/languages/test_CSharp.py new file mode 100644 index 0000000..91f6f0d --- /dev/null +++ b/tests/languages/test_CSharp.py @@ -0,0 +1,31 @@ +from codelimit.languages import CSharp +from tests.conftest import assert_functions, print_scopes + + +def test_hello_world(): + code = """ + namespace SamplePrograms + { + public class HelloWorld + { + static void Main() + { + System.Console.WriteLine("Hello, World!"); + } + } + } + """ + + assert_functions(code, CSharp(), {"Main": 4}) + + +def test_longest_word(): + code = """ + public class Foo { + public void bar() { + string[] w = sentence.Split(new[] {' '}); + } + } + """ + + assert_functions(code, CSharp(), {"bar": 3}) diff --git a/tests/languages/test_Cpp.py b/tests/languages/test_Cpp.py index 8b48b9f..e313d03 100644 --- a/tests/languages/test_Cpp.py +++ b/tests/languages/test_Cpp.py @@ -1,5 +1,5 @@ -from codelimit.languages import Languages -from tests.conftest import assert_units +from codelimit.languages import Cpp +from tests.conftest import assert_functions def test_simple_main_function(): @@ -14,7 +14,7 @@ def test_simple_main_function(): } """ - assert_units(code, Languages.Cpp, {"main": 4}) + assert_functions(code, Cpp(), {"main": 4}) def test_simple_class_function(): @@ -37,7 +37,7 @@ class Main { } """ - assert_units(code, Languages.Cpp, {"sayHello": 3, "main": 5}) + assert_functions(code, Cpp(), {"sayHello": 3, "main": 5}) def test_function(): @@ -50,7 +50,7 @@ def test_function(): } """ - assert_units(code, Languages.Cpp, {"makeInscribedOctagon": 5}) + assert_functions(code, Cpp(), {"makeInscribedOctagon": 5}) def test_namespace(): @@ -71,7 +71,7 @@ class Main { } """ - assert_units(code, Languages.Cpp, {"sayHello": 3}) + assert_functions(code, Cpp(), {"sayHello": 3}) def test_skip_function_with_nocl_comment(): @@ -81,7 +81,7 @@ def test_skip_function_with_nocl_comment(): } """ - assert_units(code, Languages.Cpp, {"foo": 3}) + assert_functions(code, Cpp(), {"foo": 3}) code = """ void foo(Bar bar) { // nocl @@ -89,4 +89,4 @@ def test_skip_function_with_nocl_comment(): } """ - assert_units(code, Languages.Cpp, {}) + assert_functions(code, Cpp(), {}) diff --git a/tests/languages/test_Java.py b/tests/languages/test_Java.py index fb58456..a8892b1 100644 --- a/tests/languages/test_Java.py +++ b/tests/languages/test_Java.py @@ -1,5 +1,5 @@ -from codelimit.languages import Languages -from tests.conftest import assert_units, print_units +from codelimit.languages import Java +from tests.conftest import assert_functions def test_simple_main_function(): @@ -11,7 +11,7 @@ def test_simple_main_function(): } """ - assert_units(code, Languages.Java, {"main": 3}) + assert_functions(code, Java(), {"main": 3}) def test_function_with_throws(): @@ -23,7 +23,7 @@ def test_function_with_throws(): } """ - assert_units(code, Languages.Java, {"foo": 3}) + assert_functions(code, Java(), {"foo": 3}) def test_two_functions(): @@ -38,7 +38,7 @@ def test_two_functions(): } """ - assert_units(code, Languages.Java, {"one": 3, "two": 3}) + assert_functions(code, Java(), {"one": 3, "two": 3}) def test_nested_class(): @@ -55,7 +55,7 @@ class Foo { } """ - assert_units(code, Languages.Java, {"Foo": 3, "foobar": 3}) + assert_functions(code, Java(), {"Foo": 3, "foobar": 3}) def test_anonymous_class(): @@ -74,9 +74,8 @@ class Foo { } } """ - print_units(code, Languages.Java) - assert_units(code, Languages.Java, {"Foo": 6, "preVisitDirectory": 6}) + assert_functions(code, Java(), {"Foo": 6, "preVisitDirectory": 6}) def test_record_class(): @@ -95,7 +94,7 @@ def test_record_class(): } """ - assert_units(code, Languages.Java, {"main": 4}) + assert_functions(code, Java(), {"main": 4}) def test_method_with_anonymous_class(): @@ -108,7 +107,7 @@ class Foo { } """ - assert_units(code, Languages.Java, {"foo": 4}) + assert_functions(code, Java(), {"foo": 4}) def test_abstract_methods(): @@ -123,7 +122,7 @@ def test_abstract_methods(): } """ - assert_units(code, Languages.Java, {'foobar': 3}) + assert_functions(code, Java(), {'foobar': 3}) def test_abstract_methods_with_inner_class(): @@ -139,4 +138,4 @@ class Bar { } """ - assert_units(code, Languages.Java, {'foobar': 3}) + assert_functions(code, Java(), {'foobar': 3}) diff --git a/tests/languages/test_JavaScript.py b/tests/languages/test_JavaScript.py index cdd936a..5ab9d78 100644 --- a/tests/languages/test_JavaScript.py +++ b/tests/languages/test_JavaScript.py @@ -1,5 +1,5 @@ -from codelimit.languages import Languages -from tests.conftest import assert_units +from codelimit.languages import JavaScript +from tests.conftest import assert_functions def test_simple_function(): @@ -9,7 +9,7 @@ def test_simple_function(): } """ - assert_units(code, Languages.JavaScript, {"foo": 3}) + assert_functions(code, JavaScript(), {"foo": 3}) def test_arrow_function(): @@ -19,7 +19,7 @@ def test_arrow_function(): } """ - assert_units(code, Languages.JavaScript, {"sayHello": 3}) + assert_functions(code, JavaScript(), {"sayHello": 3}) def test_nested_functions(): @@ -38,9 +38,9 @@ def test_nested_functions(): sayHelloWorld(); """ - assert_units( + assert_functions( code, - Languages.JavaScript, + JavaScript(), {"sayHelloWorld": 4, "sayHello": 3, "sayWorld": 3}, ) @@ -56,7 +56,8 @@ def test_top_level_anonymous_functions_are_skipped(): }); """ - assert_units(code, Languages.JavaScript, {"sayHelloWorld": 3}) + assert_functions(code, JavaScript(), {"sayHelloWorld": 3}) + def test_nested_anonymous_functions_are_skipped(): code = """ @@ -71,4 +72,4 @@ def test_nested_anonymous_functions_are_skipped(): } """ - assert_units(code, Languages.JavaScript, {"say": 5, "helloWorld": 3}) \ No newline at end of file + assert_functions(code, JavaScript(), {"say": 5, "helloWorld": 3}) diff --git a/tests/languages/test_Python.py b/tests/languages/test_Python.py index f3ef733..edcad31 100644 --- a/tests/languages/test_Python.py +++ b/tests/languages/test_Python.py @@ -1,9 +1,8 @@ from pygments.lexers import PythonLexer from codelimit.common.lexer_utils import lex -from codelimit.languages import Languages -from codelimit.languages.Python import _get_indentation, _get_token_lines -from tests.conftest import assert_units +from codelimit.languages.Python import _get_indentation, _get_token_lines, Python +from tests.conftest import assert_functions def test_simple_function(): @@ -12,7 +11,7 @@ def foo(): pass """ - assert_units(code, Languages.Python, {"foo": 2}) + assert_functions(code, Python(), {"foo": 2}) def test_simple_function_larger_block(): @@ -22,7 +21,7 @@ def foo(): spam = eggs """ - assert_units(code, Languages.Python, {"foo": 3}) + assert_functions(code, Python(), {"foo": 3}) def test_two_functions(): @@ -34,7 +33,7 @@ def bar(): foo() """ - assert_units(code, Languages.Python, {"foo": 2, "bar": 2}) + assert_functions(code, Python(), {"foo": 2, "bar": 2}) def test_return_type(): @@ -45,7 +44,7 @@ def bar( bar = foo """ - assert_units(code, Languages.Python, {"bar": 4}) + assert_functions(code, Python(), {"bar": 4}) def test_two_functions_with_return_types(): @@ -61,7 +60,7 @@ def foo( foo = bar """ - assert_units(code, Languages.Python, {"bar": 4, "foo": 4}) + assert_functions(code, Python(), {"bar": 4, "foo": 4}) def test_get_indentation(): @@ -78,7 +77,7 @@ def test_get_indentation(): def test_no_functions(): code = "" - assert_units(code, Languages.Python, {}) + assert_functions(code, Python(), {}) def test_trailing_global_code(): @@ -91,7 +90,7 @@ def foo(): ] """ - assert_units(code, Languages.Python, {"foo": 2}) + assert_functions(code, Python(), {"foo": 2}) def test_get_headers_multi_header_with_comment(): @@ -104,7 +103,7 @@ def bar(): foo() """ - assert_units(code, Languages.Python, {"foo": 2, "bar": 2}) + assert_functions(code, Python(), {"foo": 2, "bar": 2}) def test_do_not_count_comment_lines(): @@ -115,7 +114,7 @@ def foo(): # This is also a comment """ - assert_units(code, Languages.Python, {"foo": 2}) + assert_functions(code, Python(), {"foo": 2}) def test_header_with_defaults(): @@ -131,7 +130,7 @@ def foo( pass """ - assert_units(code, Languages.Python, {"foo": 9}) + assert_functions(code, Python(), {"foo": 9}) def test_header_type_hints(): @@ -142,7 +141,7 @@ def foo( pass """ - assert_units(code, Languages.Python, {"foo": 4}) + assert_functions(code, Python(), {"foo": 4}) def test_skip_function_with_nocl_comment_in_header(): @@ -159,7 +158,7 @@ def foo( bar = foo """ - assert_units(code, Languages.Python, {"foo": 5}) + assert_functions(code, Python(), {"foo": 5}) def test_function_with_type_hints(): @@ -171,7 +170,7 @@ def foo( foo = bar """ - assert_units(code, Languages.Python, {"foo": 5}) + assert_functions(code, Python(), {"foo": 5}) def test_line_continuation(): @@ -182,7 +181,7 @@ def say_hello(): "world") """ - assert_units(code, Languages.Python, {"say_hello": 4}) + assert_functions(code, Python(), {"say_hello": 4}) def test_if_statement(): @@ -195,7 +194,7 @@ def foo(): bar = foo """ - assert_units(code, Languages.Python, {"foo": 6}) + assert_functions(code, Python(), {"foo": 6}) def test_get_token_lines(): diff --git a/tests/languages/test_TypeScript.py b/tests/languages/test_TypeScript.py index fcdbad8..1a6b75b 100644 --- a/tests/languages/test_TypeScript.py +++ b/tests/languages/test_TypeScript.py @@ -1,5 +1,5 @@ -from codelimit.languages import Languages -from tests.conftest import assert_units +from codelimit.languages import Languages, TypeScript +from tests.conftest import assert_functions def test_simple_function(): @@ -9,7 +9,7 @@ def test_simple_function(): } """ - assert_units(code, Languages.TypeScript, {"foo": 3}) + assert_functions(code, Languages.by_name[TypeScript.name], {"foo": 3}) def test_arrow_function(): @@ -19,7 +19,7 @@ def test_arrow_function(): } """ - assert_units(code, Languages.TypeScript, {"sayHello": 3}) + assert_functions(code, Languages.by_name[TypeScript.name], {"sayHello": 3}) def test_nested_functions(): @@ -33,4 +33,4 @@ def test_nested_functions(): } """ - assert_units(code, Languages.TypeScript, {"Outer": 3, "sayHello": 3}) + assert_functions(code, Languages.by_name[TypeScript.name], {"Outer": 3, "sayHello": 3}) From 9cef6d3f509a796741b4dec5860932f00fdfbb64 Mon Sep 17 00:00:00 2001 From: Rob van der Leek <5324924+robvanderleek@users.noreply.github.com> Date: Fri, 17 Jan 2025 22:45:14 +0100 Subject: [PATCH 3/4] =?UTF-8?q?chore:=20=F0=9F=9A=A8=20Fix=20linter=20issu?= =?UTF-8?q?es?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- codelimit/languages/TypeScript.py | 8 +++----- codelimit/languages/__init__.py | 9 ++++++++ tests/languages/test_C.py | 18 ++++++++-------- tests/languages/test_CSharp.py | 8 ++++---- tests/languages/test_Cpp.py | 14 ++++++------- tests/languages/test_Java.py | 20 +++++++++--------- tests/languages/test_JavaScript.py | 12 +++++------ tests/languages/test_Python.py | 33 +++++++++++++++--------------- tests/languages/test_TypeScript.py | 8 ++++---- 9 files changed, 69 insertions(+), 61 deletions(-) diff --git a/codelimit/languages/TypeScript.py b/codelimit/languages/TypeScript.py index 625d32e..1a18e1c 100644 --- a/codelimit/languages/TypeScript.py +++ b/codelimit/languages/TypeScript.py @@ -6,18 +6,16 @@ from codelimit.common.scope.Header import Header from codelimit.common.scope.scope_utils import get_blocks, get_headers from codelimit.common.token_matching.predicate.Balanced import Balanced -from codelimit.common.token_matching.predicate.Or import Or from codelimit.common.token_matching.predicate.Keyword import Keyword from codelimit.common.token_matching.predicate.Name import Name from codelimit.common.token_matching.predicate.Operator import Operator +from codelimit.common.token_matching.predicate.Or import Or from codelimit.common.token_matching.predicate.Symbol import Symbol class TypeScript(Language): - name = "TypeScript" - def __init__(self): - super().__init__(self.name) + super().__init__("TypeScript") def extract_headers(self, tokens: list[Token]) -> list[Header]: functions = get_headers( @@ -40,6 +38,6 @@ def extract_headers(self, tokens: list[Token]) -> list[Header]: return functions + arrow_functions def extract_blocks( - self, tokens: list[Token], headers: list[Header] + self, tokens: list[Token], headers: list[Header] ) -> list[TokenRange]: return get_blocks(tokens, "{", "}") diff --git a/codelimit/languages/__init__.py b/codelimit/languages/__init__.py index a9976ff..8d99ad5 100644 --- a/codelimit/languages/__init__.py +++ b/codelimit/languages/__init__.py @@ -9,7 +9,16 @@ class Languages: + C = C() + Cpp = Cpp() + CSharp = CSharp() + Java = Java() + JavaScript = JavaScript() + Python = Python() + TypeScript = TypeScript() + by_name: dict[str, Language] = {} for subclass in Language.__subclasses__(): language = subclass() by_name[language.name] = language + diff --git a/tests/languages/test_C.py b/tests/languages/test_C.py index 766706e..8f83a64 100644 --- a/tests/languages/test_C.py +++ b/tests/languages/test_C.py @@ -1,4 +1,4 @@ -from codelimit.languages import C +from codelimit.languages import Languages from tests.conftest import assert_functions @@ -9,7 +9,7 @@ def test_simple_main_function(): } """ - assert_functions(code, C(), {"main": 3}) + assert_functions(code, Languages.C, {"main": 3}) def test_main_function_with_include(): @@ -21,7 +21,7 @@ def test_main_function_with_include(): } """ - assert_functions(code, C(), {"main": 4}) + assert_functions(code, Languages.C, {"main": 4}) def test_simple_function(): @@ -32,7 +32,7 @@ def test_simple_function(): } """ - assert_functions(code, C(), {"bar": 3}) + assert_functions(code, Languages.C, {"bar": 3}) def test_multiple_functions(): @@ -46,13 +46,13 @@ def test_multiple_functions(): } """ - assert_functions(code, C(), {"bar": 3, "foo": 3}) + assert_functions(code, Languages.C, {"bar": 3, "foo": 3}) def test_no_functions(): code = "" - assert_functions(code, C(), {}) + assert_functions(code, Languages.C, {}) def test_iteration_macro_is_not_a_function(): @@ -64,7 +64,7 @@ def test_iteration_macro_is_not_a_function(): } """ - assert_functions(code, C(), {"foo": 5}) + assert_functions(code, Languages.C, {"foo": 5}) def test_formatting(): @@ -78,7 +78,7 @@ def test_formatting(): } """ - assert_functions(code, C(), {"nfs_register_sysctl": 7}) + assert_functions(code, Languages.C, {"nfs_register_sysctl": 7}) def test_nested_header_but_no_body_inside_parent(): @@ -92,4 +92,4 @@ def test_nested_header_but_no_body_inside_parent(): }; """ - assert_functions(code, C(), {"foo": 5}) + assert_functions(code, Languages.C, {"foo": 5}) diff --git a/tests/languages/test_CSharp.py b/tests/languages/test_CSharp.py index 91f6f0d..b73dd45 100644 --- a/tests/languages/test_CSharp.py +++ b/tests/languages/test_CSharp.py @@ -1,5 +1,5 @@ -from codelimit.languages import CSharp -from tests.conftest import assert_functions, print_scopes +from codelimit.languages import Languages +from tests.conftest import assert_functions def test_hello_world(): @@ -16,7 +16,7 @@ def test_hello_world(): } """ - assert_functions(code, CSharp(), {"Main": 4}) + assert_functions(code, Languages.CSharp, {"Main": 4}) def test_longest_word(): @@ -28,4 +28,4 @@ def test_longest_word(): } """ - assert_functions(code, CSharp(), {"bar": 3}) + assert_functions(code, Languages.CSharp, {"bar": 3}) diff --git a/tests/languages/test_Cpp.py b/tests/languages/test_Cpp.py index e313d03..b257a56 100644 --- a/tests/languages/test_Cpp.py +++ b/tests/languages/test_Cpp.py @@ -1,4 +1,4 @@ -from codelimit.languages import Cpp +from codelimit.languages import Languages from tests.conftest import assert_functions @@ -14,7 +14,7 @@ def test_simple_main_function(): } """ - assert_functions(code, Cpp(), {"main": 4}) + assert_functions(code, Languages.Cpp, {"main": 4}) def test_simple_class_function(): @@ -37,7 +37,7 @@ class Main { } """ - assert_functions(code, Cpp(), {"sayHello": 3, "main": 5}) + assert_functions(code, Languages.Cpp, {"sayHello": 3, "main": 5}) def test_function(): @@ -50,7 +50,7 @@ def test_function(): } """ - assert_functions(code, Cpp(), {"makeInscribedOctagon": 5}) + assert_functions(code, Languages.Cpp, {"makeInscribedOctagon": 5}) def test_namespace(): @@ -71,7 +71,7 @@ class Main { } """ - assert_functions(code, Cpp(), {"sayHello": 3}) + assert_functions(code, Languages.Cpp, {"sayHello": 3}) def test_skip_function_with_nocl_comment(): @@ -81,7 +81,7 @@ def test_skip_function_with_nocl_comment(): } """ - assert_functions(code, Cpp(), {"foo": 3}) + assert_functions(code, Languages.Cpp, {"foo": 3}) code = """ void foo(Bar bar) { // nocl @@ -89,4 +89,4 @@ def test_skip_function_with_nocl_comment(): } """ - assert_functions(code, Cpp(), {}) + assert_functions(code, Languages.Cpp, {}) diff --git a/tests/languages/test_Java.py b/tests/languages/test_Java.py index a8892b1..0e5508e 100644 --- a/tests/languages/test_Java.py +++ b/tests/languages/test_Java.py @@ -1,4 +1,4 @@ -from codelimit.languages import Java +from codelimit.languages import Languages from tests.conftest import assert_functions @@ -11,7 +11,7 @@ def test_simple_main_function(): } """ - assert_functions(code, Java(), {"main": 3}) + assert_functions(code, Languages.Java, {"main": 3}) def test_function_with_throws(): @@ -23,7 +23,7 @@ def test_function_with_throws(): } """ - assert_functions(code, Java(), {"foo": 3}) + assert_functions(code, Languages.Java, {"foo": 3}) def test_two_functions(): @@ -38,7 +38,7 @@ def test_two_functions(): } """ - assert_functions(code, Java(), {"one": 3, "two": 3}) + assert_functions(code, Languages.Java, {"one": 3, "two": 3}) def test_nested_class(): @@ -55,7 +55,7 @@ class Foo { } """ - assert_functions(code, Java(), {"Foo": 3, "foobar": 3}) + assert_functions(code, Languages.Java, {"Foo": 3, "foobar": 3}) def test_anonymous_class(): @@ -75,7 +75,7 @@ class Foo { } """ - assert_functions(code, Java(), {"Foo": 6, "preVisitDirectory": 6}) + assert_functions(code, Languages.Java, {"Foo": 6, "preVisitDirectory": 6}) def test_record_class(): @@ -94,7 +94,7 @@ def test_record_class(): } """ - assert_functions(code, Java(), {"main": 4}) + assert_functions(code, Languages.Java, {"main": 4}) def test_method_with_anonymous_class(): @@ -107,7 +107,7 @@ class Foo { } """ - assert_functions(code, Java(), {"foo": 4}) + assert_functions(code, Languages.Java, {"foo": 4}) def test_abstract_methods(): @@ -122,7 +122,7 @@ def test_abstract_methods(): } """ - assert_functions(code, Java(), {'foobar': 3}) + assert_functions(code, Languages.Java, {'foobar': 3}) def test_abstract_methods_with_inner_class(): @@ -138,4 +138,4 @@ class Bar { } """ - assert_functions(code, Java(), {'foobar': 3}) + assert_functions(code, Languages.Java, {'foobar': 3}) diff --git a/tests/languages/test_JavaScript.py b/tests/languages/test_JavaScript.py index 5ab9d78..63ec4ab 100644 --- a/tests/languages/test_JavaScript.py +++ b/tests/languages/test_JavaScript.py @@ -1,4 +1,4 @@ -from codelimit.languages import JavaScript +from codelimit.languages import Languages from tests.conftest import assert_functions @@ -9,7 +9,7 @@ def test_simple_function(): } """ - assert_functions(code, JavaScript(), {"foo": 3}) + assert_functions(code, Languages.JavaScript, {"foo": 3}) def test_arrow_function(): @@ -19,7 +19,7 @@ def test_arrow_function(): } """ - assert_functions(code, JavaScript(), {"sayHello": 3}) + assert_functions(code, Languages.JavaScript, {"sayHello": 3}) def test_nested_functions(): @@ -40,7 +40,7 @@ def test_nested_functions(): assert_functions( code, - JavaScript(), + Languages.JavaScript, {"sayHelloWorld": 4, "sayHello": 3, "sayWorld": 3}, ) @@ -56,7 +56,7 @@ def test_top_level_anonymous_functions_are_skipped(): }); """ - assert_functions(code, JavaScript(), {"sayHelloWorld": 3}) + assert_functions(code, Languages.JavaScript, {"sayHelloWorld": 3}) def test_nested_anonymous_functions_are_skipped(): @@ -72,4 +72,4 @@ def test_nested_anonymous_functions_are_skipped(): } """ - assert_functions(code, JavaScript(), {"say": 5, "helloWorld": 3}) + assert_functions(code, Languages.JavaScript, {"say": 5, "helloWorld": 3}) diff --git a/tests/languages/test_Python.py b/tests/languages/test_Python.py index edcad31..c17dfb9 100644 --- a/tests/languages/test_Python.py +++ b/tests/languages/test_Python.py @@ -1,7 +1,8 @@ from pygments.lexers import PythonLexer from codelimit.common.lexer_utils import lex -from codelimit.languages.Python import _get_indentation, _get_token_lines, Python +from codelimit.languages import Languages +from codelimit.languages.Python import _get_indentation, _get_token_lines from tests.conftest import assert_functions @@ -11,7 +12,7 @@ def foo(): pass """ - assert_functions(code, Python(), {"foo": 2}) + assert_functions(code, Languages.Python, {"foo": 2}) def test_simple_function_larger_block(): @@ -21,7 +22,7 @@ def foo(): spam = eggs """ - assert_functions(code, Python(), {"foo": 3}) + assert_functions(code, Languages.Python, {"foo": 3}) def test_two_functions(): @@ -33,7 +34,7 @@ def bar(): foo() """ - assert_functions(code, Python(), {"foo": 2, "bar": 2}) + assert_functions(code, Languages.Python, {"foo": 2, "bar": 2}) def test_return_type(): @@ -44,7 +45,7 @@ def bar( bar = foo """ - assert_functions(code, Python(), {"bar": 4}) + assert_functions(code, Languages.Python, {"bar": 4}) def test_two_functions_with_return_types(): @@ -60,7 +61,7 @@ def foo( foo = bar """ - assert_functions(code, Python(), {"bar": 4, "foo": 4}) + assert_functions(code, Languages.Python, {"bar": 4, "foo": 4}) def test_get_indentation(): @@ -77,7 +78,7 @@ def test_get_indentation(): def test_no_functions(): code = "" - assert_functions(code, Python(), {}) + assert_functions(code, Languages.Python, {}) def test_trailing_global_code(): @@ -90,7 +91,7 @@ def foo(): ] """ - assert_functions(code, Python(), {"foo": 2}) + assert_functions(code, Languages.Python, {"foo": 2}) def test_get_headers_multi_header_with_comment(): @@ -103,7 +104,7 @@ def bar(): foo() """ - assert_functions(code, Python(), {"foo": 2, "bar": 2}) + assert_functions(code, Languages.Python, {"foo": 2, "bar": 2}) def test_do_not_count_comment_lines(): @@ -114,7 +115,7 @@ def foo(): # This is also a comment """ - assert_functions(code, Python(), {"foo": 2}) + assert_functions(code, Languages.Python, {"foo": 2}) def test_header_with_defaults(): @@ -130,7 +131,7 @@ def foo( pass """ - assert_functions(code, Python(), {"foo": 9}) + assert_functions(code, Languages.Python, {"foo": 9}) def test_header_type_hints(): @@ -141,7 +142,7 @@ def foo( pass """ - assert_functions(code, Python(), {"foo": 4}) + assert_functions(code, Languages.Python, {"foo": 4}) def test_skip_function_with_nocl_comment_in_header(): @@ -158,7 +159,7 @@ def foo( bar = foo """ - assert_functions(code, Python(), {"foo": 5}) + assert_functions(code, Languages.Python, {"foo": 5}) def test_function_with_type_hints(): @@ -170,7 +171,7 @@ def foo( foo = bar """ - assert_functions(code, Python(), {"foo": 5}) + assert_functions(code, Languages.Python, {"foo": 5}) def test_line_continuation(): @@ -181,7 +182,7 @@ def say_hello(): "world") """ - assert_functions(code, Python(), {"say_hello": 4}) + assert_functions(code, Languages.Python, {"say_hello": 4}) def test_if_statement(): @@ -194,7 +195,7 @@ def foo(): bar = foo """ - assert_functions(code, Python(), {"foo": 6}) + assert_functions(code, Languages.Python, {"foo": 6}) def test_get_token_lines(): diff --git a/tests/languages/test_TypeScript.py b/tests/languages/test_TypeScript.py index 1a6b75b..523cb90 100644 --- a/tests/languages/test_TypeScript.py +++ b/tests/languages/test_TypeScript.py @@ -1,4 +1,4 @@ -from codelimit.languages import Languages, TypeScript +from codelimit.languages import Languages from tests.conftest import assert_functions @@ -9,7 +9,7 @@ def test_simple_function(): } """ - assert_functions(code, Languages.by_name[TypeScript.name], {"foo": 3}) + assert_functions(code, Languages.TypeScript, {"foo": 3}) def test_arrow_function(): @@ -19,7 +19,7 @@ def test_arrow_function(): } """ - assert_functions(code, Languages.by_name[TypeScript.name], {"sayHello": 3}) + assert_functions(code, Languages.TypeScript, {"sayHello": 3}) def test_nested_functions(): @@ -33,4 +33,4 @@ def test_nested_functions(): } """ - assert_functions(code, Languages.by_name[TypeScript.name], {"Outer": 3, "sayHello": 3}) + assert_functions(code, Languages.TypeScript, {"Outer": 3, "sayHello": 3}) From 1282e0581fa69edf43cac5a3b3b4b44561ec51d3 Mon Sep 17 00:00:00 2001 From: Rob van der Leek <5324924+robvanderleek@users.noreply.github.com> Date: Fri, 17 Jan 2025 22:59:59 +0100 Subject: [PATCH 4/4] =?UTF-8?q?ci:=20=F0=9F=92=9A=20Fix=20build?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- codelimit/common/report/format_markdown.py | 3 +- codelimit/languages/__init__.py | 2 +- .../codelimit.json | 369 +++++++++++++++++- 3 files changed, 360 insertions(+), 14 deletions(-) diff --git a/codelimit/common/report/format_markdown.py b/codelimit/common/report/format_markdown.py index 9b633f2..053250a 100644 --- a/codelimit/common/report/format_markdown.py +++ b/codelimit/common/report/format_markdown.py @@ -126,5 +126,6 @@ def _print_findings_with_repository(report_units: list[ReportUnit], link = (f'https://github.com/{owner}/{name}/blob/{branch}/{unit.file}#L{unit.measurement.start.line}-L' f'{unit.measurement.end.line}') console.print( - f"| {violation_type} \[{unit.measurement.unit_name}]({link}) | {unit.measurement.value} | {unit.file} |" + f"| {violation_type} " + '\[' + unit.measurement.unit_name + ']' + f"({link}) | {unit.measurement.value} " + f"| {unit.file} |" ) diff --git a/codelimit/languages/__init__.py b/codelimit/languages/__init__.py index 8d99ad5..516a82d 100644 --- a/codelimit/languages/__init__.py +++ b/codelimit/languages/__init__.py @@ -19,6 +19,6 @@ class Languages: by_name: dict[str, Language] = {} for subclass in Language.__subclasses__(): - language = subclass() + language = subclass() # type: ignore by_name[language.name] = language diff --git a/examples/TheRenegadeCoder_sample-programs_1000-snip/codelimit.json b/examples/TheRenegadeCoder_sample-programs_1000-snip/codelimit.json index 9107b85..06b4bf2 100644 --- a/examples/TheRenegadeCoder_sample-programs_1000-snip/codelimit.json +++ b/examples/TheRenegadeCoder_sample-programs_1000-snip/codelimit.json @@ -1,8 +1,8 @@ { "version": "0.18.1", - "uuid": "5aae13b7-887c-419c-a501-fbaf1bdc6ebc", - "timestamp": "2025-01-16T09:25:52+00:00", - "root": "/private/var/folders/t2/s_70szzn7qn22cp4d2nmrjbc0000gn/T/tmpz2qbk_j7/sample-programs", + "uuid": "e0fa1097-1ec6-468e-b5fc-595e48a412f4", + "timestamp": "2025-01-17T21:59:44+00:00", + "root": "/private/var/folders/t2/s_70szzn7qn22cp4d2nmrjbc0000gn/T/tmpqjz0jke_/sample-programs", "codebase": { "totals": { "TypeScript": { @@ -33,6 +33,13 @@ "hard_to_maintain": 4, "unmaintainable": 0 }, + "C#": { + "files": 29, + "lines_of_code": 849, + "functions": 71, + "hard_to_maintain": 0, + "unmaintainable": 1 + }, "C": { "files": 26, "lines_of_code": 1248, @@ -54,7 +61,7 @@ "archive/", "scripts/" ], - "profile": [2162, 1886, 1246, 0] + "profile": [2588, 2243, 1246, 66] }, "archive/t/typescript/": { "entries": [ @@ -99,7 +106,7 @@ "c/", "p/" ], - "profile": [2096, 1815, 1210, 0] + "profile": [2522, 2172, 1210, 66] }, "archive/h/hack/": { "entries": [ @@ -200,6 +207,48 @@ ], "profile": [342, 200, 97, 0] }, + "archive/c/c-sharp/": { + "entries": [ + "LongestWord.cs", + "QuickSort.cs", + "FizzBuzz.cs", + "Baklava.cs", + "Rot13.cs", + "RemoveAllWhitespace.cs", + "JosephusProblem.cs", + "SelectionSort.cs", + "LinearSearch.cs", + "InsertionSort.cs", + "ReverseString.cs", + "SleepSort.cs", + "LongestCommonSubsequence.cs", + "HelloWorld.cs", + "PrimeNumber.cs", + "JobSequencing.cs", + "MergeSort.cs", + "Quine.cs", + "Fibonacci.cs", + "BubbleSort.cs", + "BinarySearch.cs", + "DuplicateCharacterCounter.cs", + "Capitalize.cs", + "EvenOdd.cs", + "RomanNumeral.cs", + "FractionMath.cs", + "FileInputOutput.cs", + "LongestPalindromicSubstring.cs", + "Factorial.cs" + ], + "profile": [426, 357, 0, 66] + }, + "archive/c/": { + "entries": [ + "c-sharp/", + "c-plus-plus/", + "c/" + ], + "profile": [1175, 1364, 967, 66] + }, "archive/c/c-plus-plus/": { "entries": [ "dijkstra.cpp", @@ -232,13 +281,6 @@ ], "profile": [269, 635, 571, 0] }, - "archive/c/": { - "entries": [ - "c-plus-plus/", - "c/" - ], - "profile": [749, 1007, 967, 0] - }, "archive/c/c/": { "entries": [ "hello-world.c", @@ -1127,6 +1169,309 @@ {"unit_name": "printString", "start": {"line": 22, "column": 1}, "end": {"line": 25, "column": 2}, "value": 4} ] }, + "archive/c/c-sharp/LongestWord.cs": { + "checksum": "6b2a4ac40a91bd74c2ed644a85006702", + "language": "C#", + "loc": 11, + "profile": [11, 0, 0, 0], + "measurements": [ + {"unit_name": "Main", "start": {"line": 6, "column": 24}, "end": {"line": 24, "column": 6}, "value": 11} + ] + }, + "archive/c/c-sharp/QuickSort.cs": { + "checksum": "afbda702f51f573168b7ecfd4ab00cbd", + "language": "C#", + "loc": 33, + "profile": [16, 17, 0, 0], + "measurements": [ + {"unit_name": "Sort", "start": {"line": 7, "column": 29}, "end": {"line": 18, "column": 6}, "value": 11}, + {"unit_name": "ErrorAndExit", "start": {"line": 20, "column": 24}, "end": {"line": 24, "column": 6}, "value": 5}, + {"unit_name": "Main", "start": {"line": 26, "column": 24}, "end": {"line": 42, "column": 6}, "value": 17} + ] + }, + "archive/c/c-sharp/FizzBuzz.cs": { + "checksum": "216fd4ec5593e0ce766935619b26fda6", + "language": "C#", + "loc": 25, + "profile": [8, 17, 0, 0], + "measurements": [ + {"unit_name": "FizzBuzz", "start": {"line": 5, "column": 30}, "end": {"line": 21, "column": 10}, "value": 17}, + {"unit_name": "Main", "start": {"line": 23, "column": 29}, "end": {"line": 30, "column": 10}, "value": 8} + ] + }, + "archive/c/c-sharp/Baklava.cs": { + "checksum": "fbc9ebc9734a3076519dc1e18b170afa", + "language": "C#", + "loc": 11, + "profile": [11, 0, 0, 0], + "measurements": [ + {"unit_name": "Main", "start": {"line": 6, "column": 17}, "end": {"line": 19, "column": 6}, "value": 11} + ] + }, + "archive/c/c-sharp/Rot13.cs": { + "checksum": "aca5d2355a2fe3fcf34da389f1110a72", + "language": "C#", + "loc": 32, + "profile": [32, 0, 0, 0], + "measurements": [ + {"unit_name": "Encrypt", "start": {"line": 15, "column": 28}, "end": {"line": 28, "column": 10}, "value": 12}, + {"unit_name": "ExitWithError", "start": {"line": 30, "column": 28}, "end": {"line": 34, "column": 10}, "value": 5}, + {"unit_name": "Main", "start": {"line": 36, "column": 28}, "end": {"line": 50, "column": 10}, "value": 15} + ] + }, + "archive/c/c-sharp/RemoveAllWhitespace.cs": { + "checksum": "697f556df1e6fd21790e7b8d59fb55a9", + "language": "C#", + "loc": 21, + "profile": [21, 0, 0, 0], + "measurements": [ + {"unit_name": "ExitWithError", "start": {"line": 7, "column": 24}, "end": {"line": 11, "column": 6}, "value": 5}, + {"unit_name": "RemoveAllWhitespace", "start": {"line": 13, "column": 24}, "end": {"line": 21, "column": 6}, "value": 9}, + {"unit_name": "Main", "start": {"line": 23, "column": 17}, "end": {"line": 29, "column": 6}, "value": 7} + ] + }, + "archive/c/c-sharp/JosephusProblem.cs": { + "checksum": "c4ecb4fbde17ebfdd3506e0b896eb853", + "language": "C#", + "loc": 24, + "profile": [24, 0, 0, 0], + "measurements": [ + {"unit_name": "Main", "start": {"line": 9, "column": 21}, "end": {"line": 26, "column": 10}, "value": 15}, + {"unit_name": "FindJosephusPosition", "start": {"line": 28, "column": 20}, "end": {"line": 38, "column": 10}, "value": 9} + ] + }, + "archive/c/c-sharp/SelectionSort.cs": { + "checksum": "063c2736caee2714105aaca22bc905b4", + "language": "C#", + "loc": 31, + "profile": [14, 17, 0, 0], + "measurements": [ + {"unit_name": "Selection", "start": {"line": 7, "column": 36}, "end": {"line": 15, "column": 6}, "value": 9}, + {"unit_name": "ErrorAndExit", "start": {"line": 17, "column": 24}, "end": {"line": 21, "column": 6}, "value": 5}, + {"unit_name": "Main", "start": {"line": 23, "column": 24}, "end": {"line": 39, "column": 6}, "value": 17} + ] + }, + "archive/c/c-sharp/LinearSearch.cs": { + "checksum": "8a88ab3dc22ea8b641e264745592fa27", + "language": "C#", + "loc": 29, + "profile": [29, 0, 0, 0], + "measurements": [ + {"unit_name": "Search", "start": {"line": 7, "column": 24}, "end": {"line": 17, "column": 6}, "value": 11}, + {"unit_name": "ErrorAndExit", "start": {"line": 19, "column": 24}, "end": {"line": 23, "column": 6}, "value": 5}, + {"unit_name": "Main", "start": {"line": 25, "column": 24}, "end": {"line": 37, "column": 6}, "value": 13} + ] + }, + "archive/c/c-sharp/InsertionSort.cs": { + "checksum": "9be7114c7e476a06e2023f2e8fe2af79", + "language": "C#", + "loc": 37, + "profile": [20, 17, 0, 0], + "measurements": [ + {"unit_name": "Insertion", "start": {"line": 7, "column": 29}, "end": {"line": 13, "column": 6}, "value": 7}, + {"unit_name": "Insert", "start": {"line": 15, "column": 29}, "end": {"line": 22, "column": 6}, "value": 8}, + {"unit_name": "ErrorAndExit", "start": {"line": 24, "column": 24}, "end": {"line": 28, "column": 6}, "value": 5}, + {"unit_name": "Main", "start": {"line": 30, "column": 24}, "end": {"line": 46, "column": 6}, "value": 17} + ] + }, + "archive/c/c-sharp/ReverseString.cs": { + "checksum": "1def91d277dddc3b8eba5993ed4e2f66", + "language": "C#", + "loc": 13, + "profile": [13, 0, 0, 0], + "measurements": [ + {"unit_name": "Reverse", "start": {"line": 7, "column": 30}, "end": {"line": 12, "column": 10}, "value": 6}, + {"unit_name": "Main", "start": {"line": 14, "column": 28}, "end": {"line": 20, "column": 10}, "value": 7} + ] + }, + "archive/c/c-sharp/SleepSort.cs": { + "checksum": "253dc4826051c6bcdf8ea20f14f61f18", + "language": "C#", + "loc": 25, + "profile": [5, 20, 0, 0], + "measurements": [ + {"unit_name": "ErrorAndExit", "start": {"line": 8, "column": 24}, "end": {"line": 12, "column": 6}, "value": 5}, + {"unit_name": "Main", "start": {"line": 14, "column": 24}, "end": {"line": 36, "column": 6}, "value": 20} + ] + }, + "archive/c/c-sharp/LongestCommonSubsequence.cs": { + "checksum": "d475685b9b021cb103182ef6fa76ece6", + "language": "C#", + "loc": 23, + "profile": [23, 0, 0, 0], + "measurements": [ + {"unit_name": "LCS", "start": {"line": 9, "column": 44}, "end": {"line": 18, "column": 10}, "value": 8}, + {"unit_name": "Main", "start": {"line": 23, "column": 28}, "end": {"line": 37, "column": 10}, "value": 15} + ] + }, + "archive/c/c-sharp/HelloWorld.cs": { + "checksum": "a6f9560b27afd4ffa6cc0ea4eefcce70", + "language": "C#", + "loc": 4, + "profile": [4, 0, 0, 0], + "measurements": [ + {"unit_name": "Main", "start": {"line": 5, "column": 21}, "end": {"line": 8, "column": 10}, "value": 4} + ] + }, + "archive/c/c-sharp/PrimeNumber.cs": { + "checksum": "467de4c534f30cdcafe06ce0df12cf30", + "language": "C#", + "loc": 32, + "profile": [13, 19, 0, 0], + "measurements": [ + {"unit_name": "IsPrime", "start": {"line": 8, "column": 28}, "end": {"line": 22, "column": 10}, "value": 13}, + {"unit_name": "Main", "start": {"line": 24, "column": 28}, "end": {"line": 42, "column": 10}, "value": 19} + ] + }, + "archive/c/c-sharp/JobSequencing.cs": { + "checksum": "0bf4e9eed47febfbd03425fee0f8d292", + "language": "C#", + "loc": 43, + "profile": [5, 38, 0, 0], + "measurements": [ + {"unit_name": "Job", "start": {"line": 12, "column": 12}, "end": {"line": 16, "column": 6}, "value": 5}, + {"unit_name": "Main", "start": {"line": 21, "column": 17}, "end": {"line": 51, "column": 6}, "value": 18}, + {"unit_name": "GetMaxProfitJobSequence", "start": {"line": 54, "column": 29}, "end": {"line": 85, "column": 6}, "value": 20} + ] + }, + "archive/c/c-sharp/MergeSort.cs": { + "checksum": "3ad95112093140b80766eccb7996bdac", + "language": "C#", + "loc": 51, + "profile": [18, 33, 0, 0], + "measurements": [ + {"unit_name": "Sort", "start": {"line": 8, "column": 35}, "end": {"line": 20, "column": 6}, "value": 13}, + {"unit_name": "Merge", "start": {"line": 22, "column": 29}, "end": {"line": 37, "column": 6}, "value": 16}, + {"unit_name": "ErrorAndExit", "start": {"line": 39, "column": 24}, "end": {"line": 43, "column": 6}, "value": 5}, + {"unit_name": "Main", "start": {"line": 45, "column": 24}, "end": {"line": 61, "column": 6}, "value": 17} + ] + }, + "archive/c/c-sharp/Quine.cs": { + "checksum": "cd19d1608d4e8826d6414f1de6fe1e7a", + "language": "C#", + "loc": 1, + "profile": [1, 0, 0, 0], + "measurements": [ + {"unit_name": "Main", "start": {"line": 1, "column": 27}, "end": {"line": 1, "column": 194}, "value": 1} + ] + }, + "archive/c/c-sharp/Fibonacci.cs": { + "checksum": "cb8fb19ae19fba2a16c1cc7357093bec", + "language": "C#", + "loc": 22, + "profile": [0, 22, 0, 0], + "measurements": [ + {"unit_name": "Main", "start": {"line": 7, "column": 28}, "end": {"line": 28, "column": 10}, "value": 22} + ] + }, + "archive/c/c-sharp/BubbleSort.cs": { + "checksum": "59a149aa622d07067f6875af50029366", + "language": "C#", + "loc": 51, + "profile": [17, 34, 0, 0], + "measurements": [ + {"unit_name": "BubbleSort", "start": {"line": 7, "column": 29}, "end": {"line": 18, "column": 6}, "value": 12}, + {"unit_name": "PassList", "start": {"line": 20, "column": 29}, "end": {"line": 36, "column": 6}, "value": 17}, + {"unit_name": "ErrorAndExit", "start": {"line": 38, "column": 24}, "end": {"line": 42, "column": 6}, "value": 5}, + {"unit_name": "Main", "start": {"line": 44, "column": 24}, "end": {"line": 60, "column": 6}, "value": 17} + ] + }, + "archive/c/c-sharp/BinarySearch.cs": { + "checksum": "51b6e4a3306aed06962f0a27d560c914", + "language": "C#", + "loc": 47, + "profile": [9, 38, 0, 0], + "measurements": [ + {"unit_name": "Search", "start": {"line": 7, "column": 24}, "end": {"line": 28, "column": 6}, "value": 18}, + {"unit_name": "if", "start": {"line": 18, "column": 18}, "end": {"line": 21, "column": 14}, "value": 4}, + {"unit_name": "ErrorAndExit", "start": {"line": 30, "column": 24}, "end": {"line": 34, "column": 6}, "value": 5}, + {"unit_name": "Main", "start": {"line": 36, "column": 24}, "end": {"line": 57, "column": 6}, "value": 20} + ] + }, + "archive/c/c-sharp/DuplicateCharacterCounter.cs": { + "checksum": "bebcab9263ea744cdbe7856b145d8f6a", + "language": "C#", + "loc": 27, + "profile": [0, 27, 0, 0], + "measurements": [ + {"unit_name": "Main", "start": {"line": 6, "column": 24}, "end": {"line": 38, "column": 6}, "value": 27} + ] + }, + "archive/c/c-sharp/Capitalize.cs": { + "checksum": "1e8897d54588dc9d0e21726e9a41cb11", + "language": "C#", + "loc": 11, + "profile": [11, 0, 0, 0], + "measurements": [ + {"unit_name": "Main", "start": {"line": 8, "column": 21}, "end": {"line": 18, "column": 10}, "value": 11} + ] + }, + "archive/c/c-sharp/EvenOdd.cs": { + "checksum": "fac6179595a37eeca66e525a3f4a7e81", + "language": "C#", + "loc": 14, + "profile": [14, 0, 0, 0], + "measurements": [ + {"unit_name": "Main", "start": {"line": 7, "column": 28}, "end": {"line": 20, "column": 10}, "value": 14} + ] + }, + "archive/c/c-sharp/RomanNumeral.cs": { + "checksum": "93c003bc1aab90c1204b43adad4f89cc", + "language": "C#", + "loc": 30, + "profile": [13, 17, 0, 0], + "measurements": [ + {"unit_name": "RomanToDecimal", "start": {"line": 19, "column": 28}, "end": {"line": 33, "column": 10}, "value": 13}, + {"unit_name": "Main", "start": {"line": 35, "column": 28}, "end": {"line": 51, "column": 10}, "value": 17} + ] + }, + "archive/c/c-sharp/FractionMath.cs": { + "checksum": "0540769e6e1445605d1be0313b0ed14a", + "language": "C#", + "loc": 112, + "profile": [46, 0, 0, 66], + "measurements": [ + {"unit_name": "FractionMath", "start": {"line": 10, "column": 16}, "end": {"line": 19, "column": 10}, "value": 9}, + {"unit_name": "GCD", "start": {"line": 24, "column": 21}, "end": {"line": 33, "column": 10}, "value": 10}, + {"unit_name": "Simplify", "start": {"line": 35, "column": 22}, "end": {"line": 46, "column": 10}, "value": 11}, + {"unit_name": "ToString", "start": {"line": 48, "column": 32}, "end": {"line": 52, "column": 10}, "value": 5}, + {"unit_name": "Parse", "start": {"line": 54, "column": 36}, "end": {"line": 66, "column": 10}, "value": 11}, + {"unit_name": "Main", "start": {"line": 126, "column": 28}, "end": {"line": 194, "column": 10}, "value": 66} + ] + }, + "archive/c/c-sharp/FileInputOutput.cs": { + "checksum": "b274b1157fcad20351ef612dc8c2b6a7", + "language": "C#", + "loc": 5, + "profile": [5, 0, 0, 0], + "measurements": [ + {"unit_name": "Main", "start": {"line": 14, "column": 28}, "end": {"line": 18, "column": 10}, "value": 5} + ] + }, + "archive/c/c-sharp/LongestPalindromicSubstring.cs": { + "checksum": "140d089fde3f7a1bcef679fdf4c0f0fb", + "language": "C#", + "loc": 54, + "profile": [33, 21, 0, 0], + "measurements": [ + {"unit_name": "Main", "start": {"line": 8, "column": 28}, "end": {"line": 12, "column": 10}, "value": 5}, + {"unit_name": "LongestPalindrome", "start": {"line": 14, "column": 30}, "end": {"line": 37, "column": 10}, "value": 21}, + {"unit_name": "ExpandAroundCenter", "start": {"line": 39, "column": 28}, "end": {"line": 47, "column": 10}, "value": 9}, + {"unit_name": "ContainsPalindrome", "start": {"line": 49, "column": 29}, "end": {"line": 62, "column": 10}, "value": 13}, + {"unit_name": "Reverse", "start": {"line": 64, "column": 31}, "end": {"line": 69, "column": 10}, "value": 6} + ] + }, + "archive/c/c-sharp/Factorial.cs": { + "checksum": "5d62f74dc37f768692cb53dd13d8a62e", + "language": "C#", + "loc": 30, + "profile": [10, 20, 0, 0], + "measurements": [ + {"unit_name": "Fact", "start": {"line": 8, "column": 34}, "end": {"line": 13, "column": 10}, "value": 6}, + {"unit_name": "Main", "start": {"line": 15, "column": 28}, "end": {"line": 37, "column": 10}, "value": 20}, + {"unit_name": "if", "start": {"line": 25, "column": 22}, "end": {"line": 28, "column": 18}, "value": 4} + ] + }, "archive/c/c-plus-plus/dijkstra.cpp": { "checksum": "a13debbf0ff15e104c1141e7fb0639bd", "language": "C++",