├── .codeclimate.yml ├── .github ├── ISSUE_TEMPLATE │ ├── bug_report.md │ ├── custom.md │ └── feature_request.md └── workflows │ ├── go.yml │ └── release.yml ├── .gitignore ├── .travis.yml ├── CHANGELOG.md ├── CNAME ├── CODE_OF_CONDUCT.md ├── LICENSE ├── Makefile ├── README.md ├── _config.yml ├── _fixtures ├── bs │ ├── ComplexIf.java │ ├── DataClass.java │ ├── LargeClass.java │ ├── LazyClass.java │ ├── LongMethod.java │ ├── LongParameter.java │ ├── MultipleIf.java │ ├── graphcall │ │ ├── GraphCallA.java │ │ ├── GraphCallB.java │ │ └── GraphCallC.java │ └── interface │ │ └── BlogRepository.java ├── call │ ├── BookController.java │ └── call_api_test.json ├── cloc │ ├── .gitignore │ ├── normal │ │ └── pkg │ │ │ ├── DataClass.java │ │ │ └── hello.kt │ ├── someignore │ │ └── .idea │ │ │ └── hello.java │ └── summary │ │ └── android.json ├── count │ └── call.json ├── deps │ ├── gradle │ │ └── build.gradle │ ├── gradle_sample │ │ ├── build.gradle │ │ ├── settings.gradle │ │ └── src │ │ │ ├── main │ │ │ ├── java │ │ │ │ └── com │ │ │ │ │ └── phodal │ │ │ │ │ └── coco │ │ │ │ │ └── gradledemo │ │ │ │ │ └── GradledemoApplication.java │ │ │ └── resources │ │ │ │ └── application.properties │ │ │ └── test │ │ │ └── java │ │ │ └── com │ │ │ └── phodal │ │ │ └── coco │ │ │ └── gradledemo │ │ │ └── GradledemoApplicationTests.java │ ├── maven │ │ └── pom.xml │ └── maven_sample │ │ ├── .gitignore │ │ ├── pom.xml │ │ └── src │ │ ├── main │ │ ├── java │ │ │ └── com │ │ │ │ └── phodal │ │ │ │ └── coca │ │ │ │ └── depanalysis │ │ │ │ └── DepanalysisApplication.java │ │ └── resources │ │ │ └── application.properties │ │ └── test │ │ └── java │ │ └── com │ │ └── phodal │ │ └── coca │ │ └── depanalysis │ │ └── DepanalysisApplicationTests.java ├── evaluate │ ├── checkfornull │ │ └── StreamCheckForNull.java │ ├── null │ │ └── StreamNonNull.java │ ├── service.json │ ├── service_lifecycle.json │ ├── service_long_parameters.json │ ├── service_same_return_type.json │ └── utils │ │ └── UrlUtil.java ├── grammar │ ├── java │ │ ├── arch │ │ │ └── step2-java │ │ │ │ ├── Main.java │ │ │ │ ├── domain │ │ │ │ ├── AggregateRoot.java │ │ │ │ ├── AggregateRootA.java │ │ │ │ ├── AggregateRootB.java │ │ │ │ ├── Entity.java │ │ │ │ ├── EntityB.java │ │ │ │ ├── Provider.java │ │ │ │ ├── Router.java │ │ │ │ ├── ValueObject.java │ │ │ │ ├── ValueObjectC.java │ │ │ │ └── ValueObjectD.java │ │ │ │ ├── gateways │ │ │ │ └── FakeRouter.java │ │ │ │ ├── repositories │ │ │ │ ├── AggregateRootARepo.java │ │ │ │ └── Repository.java │ │ │ │ └── results.json │ │ ├── examples │ │ │ ├── annotaion_api │ │ │ │ ├── DemoController.java │ │ │ │ └── ManageController.java │ │ │ ├── api │ │ │ │ ├── BookController.java │ │ │ │ ├── BookFactory.java │ │ │ │ ├── BookMapper.java │ │ │ │ ├── BookRepository.java │ │ │ │ ├── BookService.java │ │ │ │ ├── mapper │ │ │ │ │ ├── BookMapper.xml │ │ │ │ │ └── mybatis-3-mapper.dtd │ │ │ │ └── model │ │ │ │ │ ├── Book.java │ │ │ │ │ ├── BookRepresentaion.java │ │ │ │ │ └── command │ │ │ │ │ ├── CreateBookCommand.java │ │ │ │ │ └── UpdateBookCommand.java │ │ │ ├── bs │ │ │ │ ├── DataClass.java │ │ │ │ ├── LongMethod.java │ │ │ │ └── MultipleIf.java │ │ │ ├── builder_call │ │ │ │ └── PublishedBlogResource.java │ │ │ ├── configs │ │ │ │ ├── move.coca │ │ │ │ └── rename.coca │ │ │ ├── flink │ │ │ │ └── TopProductTask.java │ │ │ ├── interface_api │ │ │ │ ├── BlogPO.java │ │ │ │ ├── BlogRepository.java │ │ │ │ └── BlogRepositoryImpl.java │ │ │ ├── lambda │ │ │ │ ├── BlogPO.java │ │ │ │ └── LambdaExample.java │ │ │ ├── method-call │ │ │ │ └── BlogRepositoryImpl.java │ │ │ ├── move-demo │ │ │ │ └── src │ │ │ │ │ └── wowo │ │ │ │ │ ├── ImportExample.java │ │ │ │ │ ├── Main.java │ │ │ │ │ ├── a │ │ │ │ │ ├── ImportForB.java │ │ │ │ │ └── OriginExample.java │ │ │ │ │ ├── b │ │ │ │ │ ├── OriginExample.java │ │ │ │ │ └── PlaceHolder.java │ │ │ │ │ ├── d │ │ │ │ │ └── IInterfaceUserExtends.java │ │ │ │ │ └── eext │ │ │ │ │ ├── ChildrenTwoFace.java │ │ │ │ │ └── sub │ │ │ │ │ ├── BaseFace.java │ │ │ │ │ ├── ChildFace.java │ │ │ │ │ ├── IBase.java │ │ │ │ │ └── IFace.java │ │ │ ├── poly │ │ │ │ ├── poly.java │ │ │ │ └── rename-poly.coca │ │ │ ├── rename │ │ │ │ ├── BlogPO.java │ │ │ │ └── BlogRepositoryImpl.java │ │ │ ├── sql │ │ │ │ └── hello.sql │ │ │ └── step2-Java │ │ │ │ ├── Doxyfile │ │ │ │ ├── Main.java │ │ │ │ ├── domain │ │ │ │ ├── AggregateRoot.java │ │ │ │ ├── AggregateRootA.java │ │ │ │ ├── AggregateRootB.java │ │ │ │ ├── Entity.java │ │ │ │ ├── EntityB.java │ │ │ │ ├── Provider.java │ │ │ │ ├── Router.java │ │ │ │ ├── ValueObject.java │ │ │ │ ├── ValueObjectC.java │ │ │ │ └── ValueObjectD.java │ │ │ │ ├── gateways │ │ │ │ └── FakeRouter.java │ │ │ │ └── repositories │ │ │ │ ├── AggregateRootARepo.java │ │ │ │ └── Repository.java │ │ ├── interface │ │ │ └── BlogRepository.java │ │ ├── lambda │ │ │ ├── BlogPO.java │ │ │ └── BlogRepositoryImpl.java │ │ └── regression │ │ │ ├── JobConcurrencyManager.java │ │ │ ├── AgentUtils.java2 │ │ │ ├── BuilderCallSplitIssue.java │ │ │ ├── DatevHelper.java │ │ │ ├── DoubleClass.java │ │ │ ├── DummyActivity.java │ │ │ ├── FormalParameterCall.java │ │ │ ├── HostDependentDownloadableContribution.java │ │ │ ├── InnerClass.java │ │ │ ├── JavaInner.java │ │ │ └── NormalChainCall.java │ ├── python │ │ └── blog_entity.py │ ├── sql │ │ ├── BookMapper.xml │ │ └── hello.sql │ └── typescript │ │ └── Class.ts ├── rcall │ └── constructor_call.json ├── refactor │ ├── move.config │ ├── move │ │ ├── a │ │ │ └── ImportForB.java │ │ ├── b │ │ │ └── OriginExample.java │ │ └── grammar │ │ │ ├── BlogPO.java │ │ │ ├── BlogRepository.java │ │ │ ├── BlogRepositoryImpl.java │ │ │ └── BookRepository.java │ ├── rename.config │ ├── rename_back.config │ └── unused │ │ └── Overload.java ├── suggest │ ├── builder │ │ └── Bee.java │ ├── factory │ │ ├── Bee.java │ │ └── factory_suggest.json │ ├── polymorphism │ │ └── Overload.java │ └── static │ │ └── StaticMain.java ├── tbs │ ├── demo-tbs-java-project │ │ └── src │ │ │ ├── main │ │ │ └── java │ │ │ │ └── tbs │ │ │ │ ├── Calculate.java │ │ │ │ └── XmlSanitizer.java │ │ │ └── test │ │ │ └── java │ │ │ └── tbs │ │ │ ├── AssertionRoulette.java │ │ │ ├── ConditionalTest.java │ │ │ ├── ConstructorInitialization.java │ │ │ ├── DuplicateAssert.java │ │ │ ├── EmptyTest.java │ │ │ ├── IgnoreTest.java │ │ │ ├── MagicNumberTest.java │ │ │ ├── MysteryGuest.java │ │ │ ├── RedundantAssertionTest.java │ │ │ ├── RedundantPrint.java │ │ │ ├── SleepyTest.java │ │ │ └── UnknownTest.java │ ├── regression │ │ ├── CallAssertInClassTests.java │ │ ├── CreatorNotUnknownTest.java │ │ ├── EnvironmentSystemIntegrationTests.java │ │ └── I18NTest.java │ └── usecases │ │ ├── AssertionRouletteTest.java │ │ ├── ConditionalTest.java │ │ ├── ConstructorInitializationTest.java │ │ ├── DuplicateAssertTest.java │ │ ├── EmptyTest.java │ │ ├── IgnoreTest.java │ │ ├── MagicNumberTest.java │ │ ├── MysteryGuestTest.java │ │ ├── RedundantAssertionTest.java │ │ ├── RedundantPrintTest.java │ │ ├── SleepyTest.java │ │ ├── TestersOnly.java │ │ └── UnknownTest.java ├── todo │ ├── Todo.go │ ├── Todo.java │ ├── todo.phodal │ └── todo.py ├── ts │ ├── grammar │ │ ├── AbstractClass.ts │ │ ├── Class.ts │ │ ├── Export.ts │ │ ├── Function.ts │ │ ├── Generic.ts │ │ ├── GenericClass.ts │ │ ├── GenericInterface.ts │ │ ├── Import.ts │ │ ├── Interface.ts │ │ ├── Module.ts │ │ ├── Statement.ts │ │ ├── Type.ts │ │ └── Variable.ts │ ├── regressions │ │ ├── callback_hell.ts │ │ └── import_comma_issue.ts │ └── ts-node-starter │ │ ├── .gitignore │ │ ├── package.json │ │ └── src │ │ ├── app.ts │ │ ├── config │ │ └── passport.ts │ │ ├── controllers │ │ ├── api.ts │ │ ├── contact.ts │ │ ├── home.ts │ │ └── user.ts │ │ ├── models │ │ └── User.ts │ │ ├── server.ts │ │ ├── types │ │ ├── express-flash.d.ts │ │ └── fbgraph.d.ts │ │ └── util │ │ ├── logger.ts │ │ └── secrets.ts └── visual │ ├── visual.svg │ └── visual_demo.dot ├── analysis ├── dep │ ├── app │ │ ├── dep_analysis.go │ │ └── root.go │ └── main.go ├── golang │ ├── app │ │ ├── analysis.go │ │ └── root.go │ └── main.go ├── java │ ├── app │ │ ├── analysis.go │ │ └── root.go │ └── main.go └── python │ ├── app │ ├── analysis.go │ └── root.go │ └── main.go ├── cmd ├── analysis.go ├── analysis_test.go ├── api.go ├── api_test.go ├── arch.go ├── arch_test.go ├── bs.go ├── bs_test.go ├── call.go ├── call_test.go ├── cloc.go ├── cloc_test.go ├── cmd_util │ ├── coca_output.go │ ├── deps_loader.go │ ├── file_rw_helper.go │ ├── ident_helper.go │ └── osexec.go ├── coca_test.go ├── concept.go ├── concept_test.go ├── config │ └── cmd_config.go ├── count.go ├── count_test.go ├── evaluate.go ├── evaluate_test.go ├── git.go ├── git_test.go ├── rcall.go ├── rcall_test.go ├── refactor.go ├── refactor_test.go ├── root.go ├── suggest.go ├── suggest_test.go ├── tbs.go ├── tbs_test.go ├── testdata │ ├── analysis_java.txt │ ├── api.txt │ ├── api_sort_remove.txt │ ├── cloc_directory.txt │ ├── cloc_ignore.txt │ ├── concept.txt │ ├── count.txt │ ├── deps_gradle.txt │ ├── deps_maven.txt │ ├── evaluate.txt │ ├── rcall_normal.txt │ ├── suggest_normal.txt │ ├── tbs_normal.txt │ ├── todo_filter.txt │ ├── todo_normal.txt │ └── top_file.txt ├── todo.go ├── todo_test.go ├── version.go └── version_test.go ├── coca.go ├── cocatest ├── cmd_assert.go ├── cmd_testcase.go ├── json_compare.go ├── panic_assert.go ├── testcase │ └── testcase.go └── testhelper │ ├── generate.go │ └── git_reset.go ├── codecov.yml ├── docs ├── README.md ├── adr │ ├── 0001-api-scan-sql.md │ ├── 0002-spring-mvc-to-spring-boot-transform.md │ ├── 0003-api-identify.md │ ├── 0004-handidraw-graphviz.md │ ├── 0005-evaluate-api.md │ ├── 0006-support-adapter-to-cli-framework.md │ ├── 0007-practise-go-patterns-in-coca.md │ ├── 0008-testable-evaluate.md │ ├── 0009-git-tell-file-history.md │ ├── 0010-pluginable.md │ ├── 0011-module-treemap-visualization.md │ ├── 0012-check-dependence-usage-for-module-seperate.md │ ├── 0013-performance-issue-for-antlar.md │ ├── 0014-improve-cloc-summary.md │ ├── 0015-light-weight-coca.md │ ├── 0016-git-branch-analysis.md │ └── README.md ├── compare │ ├── .gitignore │ ├── pom.xml │ └── src │ │ ├── main │ │ └── java │ │ │ ├── com │ │ │ └── compare │ │ │ │ ├── PythonIdentApp.java │ │ │ │ ├── PythonIdentListener.java │ │ │ │ ├── TsIdentApp.java │ │ │ │ ├── TsIdentListener.java │ │ │ │ └── main.java │ │ │ ├── pyantlr │ │ │ ├── PythonBaseLexer.java │ │ │ ├── PythonBaseParser.java │ │ │ ├── PythonLexer.interp │ │ │ ├── PythonLexer.java │ │ │ ├── PythonLexer.tokens │ │ │ ├── PythonParser.interp │ │ │ ├── PythonParser.java │ │ │ ├── PythonParser.tokens │ │ │ ├── PythonParserBaseListener.java │ │ │ ├── PythonParserListener.java │ │ │ └── PythonVersion.java │ │ │ └── tsantlr │ │ │ ├── TypeScriptBaseLexer.java │ │ │ ├── TypeScriptBaseParser.java │ │ │ ├── TypeScriptLexer.interp │ │ │ ├── TypeScriptLexer.java │ │ │ ├── TypeScriptLexer.tokens │ │ │ ├── TypeScriptParser.interp │ │ │ ├── TypeScriptParser.java │ │ │ ├── TypeScriptParser.tokens │ │ │ ├── TypeScriptParserBaseListener.java │ │ │ └── TypeScriptParserListener.java │ │ └── test │ │ └── java │ │ └── com │ │ └── compare │ │ ├── PythonIdentAppTest.java │ │ └── TsIdentAppTest.java ├── images │ ├── changes.png │ ├── model.sketch │ └── model.svg ├── patterns │ ├── evaluate.md │ ├── test-bad-smells.md │ └── todo.md ├── sample │ ├── api.svg │ ├── arch.svg │ ├── call_demo.svg │ ├── ddd.svg │ └── rcall.svg └── stories │ ├── 1nDSIHPWg-method-call-to-story.feature │ ├── 4c02dVfZg-NLP-from-database-Schema.feature │ ├── EPwMwfLWg-online-github-project-analysis.feature │ ├── MomaHFBWg-Code-Complexity-by-files.feature │ ├── ayGA3GfZR-NLP-from-method-Name.feature │ └── yXqVVzYWR-suggest-to-design-pattern-api.feature ├── go.mod ├── go.sum ├── languages ├── README.md ├── comment │ ├── CommentLexer.interp │ ├── CommentLexer.tokens │ └── comment_lexer.go ├── g4 │ ├── AspectJLexer.g4 │ ├── AspectJLexer.tokens │ ├── CommentLexer.g4 │ ├── GoLexer.g4 │ ├── GoParser.g4 │ ├── GroovyLexer.g4 │ ├── GroovyLexer.tokens │ ├── GroovyParser.g4 │ ├── JavaScriptLexer.g4 │ ├── JavaScriptLexer.tokens │ ├── JavaScriptParser.g4 │ ├── PythonLexer.g4 │ ├── PythonLexer.tokens │ ├── PythonParser.g4 │ └── RefactorMethodSignatureParser.g4 ├── groovy │ ├── GroovyLexer.interp │ ├── GroovyLexer.tokens │ ├── GroovyParser.interp │ ├── GroovyParser.tokens │ ├── groovy_lexer.go │ ├── groovy_parser.go │ ├── groovyparser_base_listener.go │ └── groovyparser_listener.go ├── java │ ├── JavaLexer.g4 │ ├── JavaLexer.interp │ ├── JavaLexer.tokens │ ├── JavaParser.g4 │ ├── JavaParser.interp │ ├── JavaParser.tokens │ ├── java_lexer.go │ ├── java_parser.go │ ├── javaparser_base_listener.go │ └── javaparser_listener.go ├── js │ ├── JavaScriptLexer.interp │ ├── JavaScriptLexer.tokens │ ├── JavaScriptParser.interp │ ├── JavaScriptParser.tokens │ ├── javascript_base_lexer.go │ ├── javascript_base_parser.go │ ├── javascript_lexer.go │ ├── javascript_parser.go │ ├── javascriptparser_base_listener.go │ └── javascriptparser_listener.go ├── python │ ├── PythonLexer.interp │ ├── PythonLexer.tokens │ ├── PythonParser.interp │ ├── PythonParser.tokens │ ├── python_base_lexer.go │ ├── python_base_parser.go │ ├── python_lexer.go │ ├── python_parser.go │ ├── pythonparser_base_listener.go │ └── pythonparser_listener.go └── ts │ ├── TypeScriptLexer.interp │ ├── TypeScriptLexer.tokens │ ├── TypeScriptParser.interp │ ├── TypeScriptParser.tokens │ ├── typescript_base_lexer.go │ ├── typescript_base_parser.go │ ├── typescript_lexer.go │ ├── typescript_parser.go │ ├── typescriptparser_base_listener.go │ └── typescriptparser_listener.go ├── pkg ├── adapter │ ├── cocafile │ │ ├── file_analysis_helper.go │ │ ├── file_analysis_helper_test.go │ │ └── file_filter.go │ └── shell │ │ └── git.go ├── application │ ├── analysis │ │ ├── app_concept │ │ │ └── abstract_analysis_app.go │ │ ├── common_analysis.go │ │ ├── goapp │ │ │ ├── go_ident_app.go │ │ │ └── go_ident_app_test.go │ │ ├── javaapp │ │ │ ├── java_full_app.go │ │ │ ├── java_full_app_test.go │ │ │ ├── java_identifier_app.go │ │ │ └── java_identifier_app_test.go │ │ └── pyapp │ │ │ ├── py_ident_app.go │ │ │ ├── py_ident_app_test.go │ │ │ └── testdata │ │ │ ├── compare │ │ │ ├── blog_entity.py │ │ │ └── import_stmt.json │ │ │ └── grammar │ │ │ ├── argument.py │ │ │ ├── atom.py │ │ │ ├── class.py │ │ │ ├── class_or_func_def_stmt.py │ │ │ ├── classdef.py │ │ │ ├── comprehension.py │ │ │ ├── def_parameters.py │ │ │ ├── dictorsetmaker.py │ │ │ ├── expr.py │ │ │ ├── expr_stmt.py │ │ │ ├── for_stmt.py │ │ │ ├── funcdef.py │ │ │ ├── if_stmt.py │ │ │ ├── import_stmt.py │ │ │ ├── logical_test.py │ │ │ ├── simple_stmt.py │ │ │ ├── small_stmt.py │ │ │ ├── subscript.py │ │ │ ├── test.py │ │ │ ├── testlist_comp.py │ │ │ ├── tokens.py │ │ │ ├── trailer.py │ │ │ ├── try_stmt.py │ │ │ ├── typedargslist.py │ │ │ ├── varargslist.py │ │ │ ├── while_stmt.py │ │ │ ├── with_stmt.py │ │ │ └── yield_expr.py │ ├── api │ │ ├── java_api_app.go │ │ └── java_api_app_test.go │ ├── arch │ │ ├── arch_app.go │ │ ├── arch_app_test.go │ │ └── tequila │ │ │ ├── LICENSE │ │ │ ├── incl_viz.go │ │ │ ├── incl_viz_test.go │ │ │ ├── merge_viz.go │ │ │ └── path_trie.go │ ├── bs │ │ ├── bad_smell_app.go │ │ ├── bad_smell_app_test.go │ │ └── bs_app.go │ ├── call │ │ ├── call_graph.go │ │ ├── call_graph_test.go │ │ └── stop_words │ │ │ └── languages │ │ │ └── en.go │ ├── cloc │ │ └── cloc_app.go │ ├── concept │ │ ├── concept_analyser.go │ │ ├── concept_analyser_test.go │ │ └── concept_segmenter.go │ ├── count │ │ ├── count_app.go │ │ └── count_app_test.go │ ├── deps │ │ ├── dep_app.go │ │ ├── dep_app_test.go │ │ ├── gradle_analysis.go │ │ └── maven_analysis.go │ ├── evaluate │ │ ├── README.md │ │ ├── analyser.go │ │ ├── analyser_test.go │ │ ├── evaluate.go │ │ └── evaluator │ │ │ ├── controller.go │ │ │ ├── empty.go │ │ │ ├── models.go │ │ │ ├── null_exception.go │ │ │ ├── service.go │ │ │ ├── splitter_util.go │ │ │ └── util.go │ ├── git │ │ ├── README.md │ │ ├── changelog.go │ │ ├── changelog_test.go │ │ ├── git.go │ │ ├── git_test.go │ │ ├── log_parser.go │ │ └── models.go │ ├── rcall │ │ ├── rcall_graph.go │ │ └── rcall_graph_test.go │ ├── refactor │ │ ├── base │ │ │ ├── java_refactor_listener.go │ │ │ └── models │ │ │ │ ├── jfull_identifier.go │ │ │ │ └── jmove_struct.go │ │ ├── moveclass │ │ │ ├── move_class_app.go │ │ │ └── move_class_app_test.go │ │ ├── rename │ │ │ ├── rename_method.go │ │ │ ├── rename_method_test.go │ │ │ └── support │ │ │ │ ├── package_info_helper.go │ │ │ │ ├── package_info_helper_test.go │ │ │ │ ├── refactor_change_model.go │ │ │ │ └── related_parser.go │ │ ├── unused │ │ │ ├── remove_unused_import.go │ │ │ └── remove_unused_import_test.go │ │ └── unusedclasses │ │ │ ├── unused_classes_app.go │ │ │ └── unused_classes_app_test.go │ ├── suggest │ │ ├── suggest_app.go │ │ └── suggest_app_test.go │ ├── tbs │ │ ├── tbs_app.go │ │ └── tbs_app_test.go │ ├── todo │ │ ├── astitodo │ │ │ ├── README.md │ │ │ └── astitodo.go │ │ ├── todo_app.go │ │ └── todo_app_test.go │ └── visual │ │ ├── visual.go │ │ └── visual_test.go ├── domain │ ├── api_domain │ │ ├── call_api.go │ │ ├── call_api_test.go │ │ ├── rest_api.go │ │ └── rest_api_test.go │ ├── bs_domain │ │ ├── bad_smell.go │ │ ├── bs_node.go │ │ └── bs_node_test.go │ ├── cloc │ │ ├── cloc_summary.go │ │ └── cloc_summary_test.go │ ├── core_domain │ │ ├── code_annotation.go │ │ ├── code_call.go │ │ ├── code_data_struct.go │ │ ├── code_dependency.go │ │ ├── code_field.go │ │ ├── code_file.go │ │ ├── code_function.go │ │ ├── code_import.go │ │ ├── code_member.go │ │ ├── code_module.go │ │ ├── code_package.go │ │ ├── code_package_info.go │ │ ├── code_position.go │ │ ├── code_project.go │ │ └── code_property.go │ └── support_domain │ │ └── suggest.go └── infrastructure │ ├── apriori │ └── apriori.go │ ├── ast │ ├── ast_go │ │ ├── cocago_builder.go │ │ ├── cocago_parser.go │ │ ├── cocago_parser_test.go │ │ ├── cocago_regression_test.go │ │ ├── parser_panic_test.go │ │ └── testdata │ │ │ ├── method_call │ │ │ ├── local_var_method_call.code │ │ │ ├── local_var_method_call.json │ │ │ ├── param_method_call.code │ │ │ ├── param_method_call.json │ │ │ ├── var_inside_method_with_call.code │ │ │ └── var_inside_method_with_call.json │ │ │ ├── node_infos │ │ │ ├── anonymous_methods.code │ │ │ ├── basic_interface.code │ │ │ ├── basic_interface.json │ │ │ ├── data_struct_property.code │ │ │ ├── data_struct_property.json │ │ │ ├── hello_world.code │ │ │ ├── hello_world.json │ │ │ ├── multiple_method_call.code │ │ │ ├── multiple_method_call.json │ │ │ ├── nested_method.code │ │ │ ├── nested_method.json │ │ │ ├── normal_method.code │ │ │ ├── normal_method.json │ │ │ ├── struct_type_zero.code │ │ │ ├── struct_type_zero.json │ │ │ ├── struct_with_func.code │ │ │ ├── struct_with_func.json │ │ │ ├── struct_with_func_decl.code │ │ │ └── struct_with_func_decl.json │ │ │ └── regression │ │ │ ├── coll_stack.code │ │ │ └── coll_stack.json │ ├── ast_groovy │ │ ├── gradle_process_helper.go │ │ └── groovy_identifier_listener.go │ ├── ast_java │ │ ├── ast_api_java │ │ │ └── java_api_listener.go │ │ ├── ast_java_target_handler.go │ │ ├── common_listener │ │ │ └── common_listener.go │ │ ├── java_full_converter.go │ │ ├── java_full_listener.go │ │ ├── java_full_listener_test.go │ │ ├── java_identify │ │ │ └── java_identifier_listener.go │ │ └── java_process_helper.go │ ├── ast_python │ │ └── python_ident_listener.go │ ├── astutil │ │ ├── pare_tree_util.go │ │ └── position.go │ └── bs_java │ │ └── bad_smell_listener.go │ ├── constants │ └── java_target_config.go │ ├── container │ └── coll_stack.go │ ├── jpackage │ ├── jpackage.go │ └── jpackage_test.go │ ├── string_helper │ ├── coca_sort.go │ └── string_array.go │ └── xmlparse │ ├── LICENSE │ ├── README.md │ └── xml_parser.go ├── scripts ├── build.sh ├── compile-antlr.sh └── go.test.sh └── showcases ├── android-gradle-dsl.svg ├── android-gradle-elements.svg ├── android-studio-android-arch.svg ├── android-studio-android-merge.svg └── android-studio-call.svg /.codeclimate.yml: -------------------------------------------------------------------------------- 1 | version: "2" 2 | exclude_patterns: 3 | - "languages/" 4 | - "_fixtures/" 5 | - "wasm/" 6 | - "**/testdata/**" -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **To Reproduce** 14 | Steps to reproduce the behavior: 15 | 1. Go to '...' 16 | 2. Click on '....' 17 | 3. Scroll down to '....' 18 | 4. See error 19 | 20 | **Expected behavior** 21 | A clear and concise description of what you expected to happen. 22 | 23 | **Screenshots** 24 | If applicable, add screenshots to help explain your problem. 25 | 26 | **Desktop (please complete the following information):** 27 | - OS: [e.g. iOS] 28 | - Browser [e.g. chrome, safari] 29 | - Version [e.g. 22] 30 | 31 | **Smartphone (please complete the following information):** 32 | - Device: [e.g. iPhone6] 33 | - OS: [e.g. iOS8.1] 34 | - Browser [e.g. stock browser, safari] 35 | - Version [e.g. 22] 36 | 37 | **Additional context** 38 | Add any other context about the problem here. 39 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/custom.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Custom issue template 3 | about: Describe this issue template's purpose here. 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | 11 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /.github/workflows/go.yml: -------------------------------------------------------------------------------- 1 | name: Build 2 | 3 | on: 4 | push: 5 | branches: [ master ] 6 | pull_request: 7 | branches: [ master ] 8 | 9 | jobs: 10 | 11 | build: 12 | name: Build 13 | runs-on: ubuntu-latest 14 | steps: 15 | 16 | - name: Set up Go 1.x 17 | uses: actions/setup-go@v2 18 | with: 19 | go-version: ^1.18 20 | id: go 21 | 22 | - name: Setup Graphviz 23 | uses: ts-graphviz/setup-graphviz@v1 24 | 25 | - name: Check out code into the Go module directory 26 | uses: actions/checkout@v2 27 | 28 | - name: Get dependencies 29 | run: | 30 | go get -v -t -d ./... 31 | if [ -f Gopkg.toml ]; then 32 | curl https://raw.githubusercontent.com/golang/dep/master/install.sh | sh 33 | dep ensure 34 | fi 35 | 36 | - name: Build 37 | run: go build -v ./... 38 | 39 | - name: Test 40 | run: go test -v ./... 41 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | 3 | go: 4 | - 1.14.x 5 | - 1.15.x 6 | 7 | os: 8 | - linux 9 | - osx 10 | - windows 11 | 12 | env: 13 | global: 14 | - GO111MODULE=on 15 | - PATH=${TRAVIS_BUILD_DIR}/bin:${PATH} 16 | 17 | addons: 18 | apt: 19 | packages: 20 | - graphviz 21 | 22 | before_script: 23 | - go get github.com/onsi/gomega 24 | - go get github.com/onsi/ginkgo/ginkgo 25 | - go get github.com/modocache/gover 26 | - go get github.com/mattn/goveralls 27 | 28 | git: 29 | depth: 1 30 | 31 | install: true 32 | 33 | before_install: 34 | - go get -t -v $(go list ./... | grep -v /languages/) 35 | 36 | script: 37 | - go test -v $(go list ./... | grep -v /languages/) -coverprofile=coverage.txt -covermode=atomic -coverpkg=./... 38 | 39 | after_success: 40 | - bash <(curl -s https://codecov.io/bash) 41 | -------------------------------------------------------------------------------- /CNAME: -------------------------------------------------------------------------------- 1 | coca.migration.ink -------------------------------------------------------------------------------- /_config.yml: -------------------------------------------------------------------------------- 1 | remote_theme: phodal/mifa-jekyll 2 | -------------------------------------------------------------------------------- /_fixtures/bs/DataClass.java: -------------------------------------------------------------------------------- 1 | package com.phodal.coca.analysis.identifier.model; 2 | 3 | public class DataClass { 4 | private String date; 5 | private String time; 6 | 7 | public String getDate() { 8 | return date; 9 | } 10 | 11 | public void setDate(String date) { 12 | this.date = date; 13 | } 14 | 15 | public String getTime() { 16 | return time; 17 | } 18 | 19 | public void setTime(String time) { 20 | this.time = time; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /_fixtures/bs/LargeClass.java: -------------------------------------------------------------------------------- 1 | package com.phodal.coca.analysis.identifier.model; 2 | 3 | public class DataClass { 4 | public void method1() {} 5 | public void method2() {} 6 | public void method3() {} 7 | public void method4() {} 8 | public void method5() {} 9 | public void method6() {} 10 | public void method7() {} 11 | public void method8() {} 12 | public void method9() {} 13 | public void method10() {} 14 | public void method11() {} 15 | public void method12() {} 16 | public void method13() {} 17 | public void method14() {} 18 | public void method15() {} 19 | public void method16() {} 20 | public void method17() {} 21 | public void method18() {} 22 | public void method19() {} 23 | public void method20() {} 24 | } 25 | -------------------------------------------------------------------------------- /_fixtures/bs/LazyClass.java: -------------------------------------------------------------------------------- 1 | class LazyClass { 2 | 3 | } 4 | -------------------------------------------------------------------------------- /_fixtures/bs/LongParameter.java: -------------------------------------------------------------------------------- 1 | package com.phodal.coca.analysis.identifier.model; 2 | 3 | public class LongParameter { 4 | public void buildSomeThing(String time, int x, int y, int z, int a, int b) { 5 | 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /_fixtures/bs/MultipleIf.java: -------------------------------------------------------------------------------- 1 | class MultipleIf { 2 | public static void main(String args[]) { 3 | int i = 20; 4 | 5 | if (i == 10) 6 | System.out.println("i is 10"); 7 | if (i == 15) 8 | System.out.println("i is 15"); 9 | if (i == 20) 10 | System.out.println("i is 20"); 11 | if (i == 20) 12 | System.out.println("i is 20"); 13 | if (i == 20) 14 | System.out.println("i is 20"); 15 | if (i == 20) 16 | System.out.println("i is 20"); 17 | if (i == 20) 18 | System.out.println("i is 20"); 19 | if (i == 20) 20 | System.out.println("i is 20"); 21 | else 22 | System.out.println("i is not present"); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /_fixtures/bs/graphcall/GraphCallA.java: -------------------------------------------------------------------------------- 1 | 2 | package graphcall; 3 | 4 | public class GraphCallA { 5 | private GraphCallB graphCallB; 6 | private GraphCallC graphCallC; 7 | 8 | public void sayHi(){ 9 | graphCallB.sayHi(); 10 | graphCallC.sayHi(); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /_fixtures/bs/graphcall/GraphCallB.java: -------------------------------------------------------------------------------- 1 | package graphcall; 2 | 3 | public class GraphCallB { 4 | private GraphCallC graphCallC; 5 | 6 | public void sayHi(){ 7 | graphCallC.sayHi(); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /_fixtures/bs/graphcall/GraphCallC.java: -------------------------------------------------------------------------------- 1 | package graphcall; 2 | 3 | public class GraphCallC { 4 | 5 | public void sayHi(){ 6 | System.out.println("hi"); 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /_fixtures/bs/interface/BlogRepository.java: -------------------------------------------------------------------------------- 1 | package study.huhao.demo.domain.models.blog; 2 | 3 | import study.huhao.demo.domain.core.Page; 4 | import study.huhao.demo.domain.core.Repository; 5 | 6 | import java.util.Optional; 7 | import java.util.UUID; 8 | 9 | public interface BlogRepository extends Repository { 10 | void save(Blog blog); 11 | 12 | Optional findById(UUID id); 13 | 14 | boolean existsById(UUID id); 15 | 16 | void deleteById(UUID id); 17 | 18 | Page findAllWithPagination(BlogCriteria criteria); 19 | } 20 | -------------------------------------------------------------------------------- /_fixtures/cloc/.gitignore: -------------------------------------------------------------------------------- 1 | !someignore/.idea/ 2 | -------------------------------------------------------------------------------- /_fixtures/cloc/normal/pkg/DataClass.java: -------------------------------------------------------------------------------- 1 | package com.phodal.coca.analysis.identifier.model; 2 | 3 | public class DataClass { 4 | private String date; 5 | private String time; 6 | 7 | public String getDate() { 8 | return date; 9 | } 10 | 11 | public void setDate(String date) { 12 | this.date = date; 13 | } 14 | 15 | public String getTime() { 16 | return time; 17 | } 18 | 19 | public void setTime(String time) { 20 | this.time = time; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /_fixtures/cloc/normal/pkg/hello.kt: -------------------------------------------------------------------------------- 1 | fun main(args: Array) { 2 | println("Hello World!") 3 | } 4 | -------------------------------------------------------------------------------- /_fixtures/cloc/someignore/.idea/hello.java: -------------------------------------------------------------------------------- 1 | package com.phodal.coca.analysis.identifier.model; 2 | 3 | public class DataClass { 4 | private String date; 5 | private String time; 6 | 7 | public String getDate() { 8 | return date; 9 | } 10 | 11 | public void setDate(String date) { 12 | this.date = date; 13 | } 14 | 15 | public String getTime() { 16 | return time; 17 | } 18 | 19 | public void setTime(String time) { 20 | this.time = time; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /_fixtures/deps/gradle_sample/settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'gradledemo' 2 | -------------------------------------------------------------------------------- /_fixtures/deps/gradle_sample/src/main/java/com/phodal/coco/gradledemo/GradledemoApplication.java: -------------------------------------------------------------------------------- 1 | package com.phodal.coco.gradledemo; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class GradledemoApplication { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(GradledemoApplication.class, args); 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /_fixtures/deps/gradle_sample/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /_fixtures/deps/gradle_sample/src/test/java/com/phodal/coco/gradledemo/GradledemoApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.phodal.coco.gradledemo; 2 | 3 | import org.junit.jupiter.api.Test; 4 | import org.springframework.boot.test.context.SpringBootTest; 5 | 6 | @SpringBootTest 7 | class GradledemoApplicationTests { 8 | 9 | @Test 10 | void contextLoads() { 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /_fixtures/deps/maven_sample/.gitignore: -------------------------------------------------------------------------------- 1 | !src/main/java/**/* 2 | !src/test/java/**/* -------------------------------------------------------------------------------- /_fixtures/deps/maven_sample/src/main/java/com/phodal/coca/depanalysis/DepanalysisApplication.java: -------------------------------------------------------------------------------- 1 | package com.phodal.coca.depanalysis; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class DepanalysisApplication { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(DepanalysisApplication.class, args); 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /_fixtures/deps/maven_sample/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /_fixtures/deps/maven_sample/src/test/java/com/phodal/coca/depanalysis/DepanalysisApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.phodal.coca.depanalysis; 2 | 3 | import org.junit.jupiter.api.Test; 4 | import org.springframework.boot.test.context.SpringBootTest; 5 | 6 | @SpringBootTest 7 | class DepanalysisApplicationTests { 8 | 9 | @Test 10 | void contextLoads() { 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /_fixtures/evaluate/checkfornull/StreamCheckForNull.java: -------------------------------------------------------------------------------- 1 | package checkfornull; 2 | 3 | import javax.annotation.CheckForNull; 4 | 5 | public class StreamCheckForNull { 6 | @CheckForNull 7 | public static String orElseNull() { 8 | 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /_fixtures/grammar/java/arch/step2-java/Main.java: -------------------------------------------------------------------------------- 1 | import domain.*; 2 | import gateways.*; 3 | import repositories.*; 4 | 5 | 6 | public class Main { 7 | 8 | public static void main(String[] args) { 9 | System.out.println("main"); 10 | Router router = new FakeRouter(); 11 | AggregateRootARepo repo = new AggregateRootARepo(); 12 | repo.save(new AggregateRootA(router)); 13 | 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /_fixtures/grammar/java/arch/step2-java/domain/AggregateRoot.java: -------------------------------------------------------------------------------- 1 | package domain; 2 | 3 | public class AggregateRoot extends Entity { 4 | 5 | 6 | } -------------------------------------------------------------------------------- /_fixtures/grammar/java/arch/step2-java/domain/AggregateRootA.java: -------------------------------------------------------------------------------- 1 | package domain; 2 | 3 | 4 | public class AggregateRootA extends AggregateRoot { 5 | 6 | private EntityB entity_b; 7 | private ValueObjectC vo_c; 8 | private Router router; 9 | private AggregateRootB b; 10 | 11 | public AggregateRootA(Router router) { 12 | this.router = router; 13 | } 14 | public void init() { 15 | router.select(); 16 | } 17 | 18 | } -------------------------------------------------------------------------------- /_fixtures/grammar/java/arch/step2-java/domain/AggregateRootB.java: -------------------------------------------------------------------------------- 1 | package domain; 2 | 3 | 4 | public class AggregateRootB extends AggregateRoot { 5 | 6 | private AggregateRootA a; 7 | 8 | } -------------------------------------------------------------------------------- /_fixtures/grammar/java/arch/step2-java/domain/Entity.java: -------------------------------------------------------------------------------- 1 | package domain; 2 | 3 | 4 | public class Entity { 5 | 6 | public int id; 7 | 8 | } -------------------------------------------------------------------------------- /_fixtures/grammar/java/arch/step2-java/domain/EntityB.java: -------------------------------------------------------------------------------- 1 | package domain; 2 | 3 | 4 | public class EntityB extends Entity { 5 | 6 | private ValueObjectD vo_d; 7 | } -------------------------------------------------------------------------------- /_fixtures/grammar/java/arch/step2-java/domain/Provider.java: -------------------------------------------------------------------------------- 1 | package domain; 2 | 3 | 4 | public class Provider { 5 | 6 | 7 | } -------------------------------------------------------------------------------- /_fixtures/grammar/java/arch/step2-java/domain/Router.java: -------------------------------------------------------------------------------- 1 | package domain; 2 | 3 | 4 | public class Router extends Provider { 5 | 6 | public int select() { 7 | return 0; 8 | } 9 | 10 | } -------------------------------------------------------------------------------- /_fixtures/grammar/java/arch/step2-java/domain/ValueObject.java: -------------------------------------------------------------------------------- 1 | package domain; 2 | 3 | 4 | public class ValueObject { 5 | 6 | 7 | } -------------------------------------------------------------------------------- /_fixtures/grammar/java/arch/step2-java/domain/ValueObjectC.java: -------------------------------------------------------------------------------- 1 | package domain; 2 | 3 | 4 | public class ValueObjectC extends ValueObject { 5 | 6 | 7 | } -------------------------------------------------------------------------------- /_fixtures/grammar/java/arch/step2-java/domain/ValueObjectD.java: -------------------------------------------------------------------------------- 1 | package domain; 2 | 3 | 4 | public class ValueObjectD extends ValueObject { 5 | 6 | 7 | } -------------------------------------------------------------------------------- /_fixtures/grammar/java/arch/step2-java/gateways/FakeRouter.java: -------------------------------------------------------------------------------- 1 | package gateways; 2 | 3 | import domain.*; 4 | 5 | 6 | public class FakeRouter extends Router { 7 | public int select(){ 8 | System.out.println("routed \n"); 9 | return 1; 10 | }; 11 | } -------------------------------------------------------------------------------- /_fixtures/grammar/java/arch/step2-java/repositories/AggregateRootARepo.java: -------------------------------------------------------------------------------- 1 | package repositories; 2 | 3 | import domain.*; 4 | 5 | 6 | public class AggregateRootARepo extends Repository { 7 | private AggregateRootA[] arList; 8 | public void save(AggregateRootA a){ 9 | System.out.println("saved\n"); 10 | }; 11 | } -------------------------------------------------------------------------------- /_fixtures/grammar/java/arch/step2-java/repositories/Repository.java: -------------------------------------------------------------------------------- 1 | package repositories; 2 | 3 | import domain.*; 4 | 5 | 6 | public class Repository { 7 | 8 | } -------------------------------------------------------------------------------- /_fixtures/grammar/java/examples/annotaion_api/ManageController.java: -------------------------------------------------------------------------------- 1 | package com.zheng.cms.admin.controller; 2 | 3 | import com.zheng.common.base.BaseController; 4 | import io.swagger.annotations.Api; 5 | import io.swagger.annotations.ApiOperation; 6 | import org.slf4j.Logger; 7 | import org.slf4j.LoggerFactory; 8 | import org.springframework.stereotype.Controller; 9 | import org.springframework.web.bind.annotation.RequestMapping; 10 | import org.springframework.web.bind.annotation.RequestMethod; 11 | 12 | /** 13 | * 后台controller 14 | * Created by ZhangShuzheng on 2017/01/12. 15 | */ 16 | @Controller 17 | @RequestMapping("/manage") 18 | @Api(value = "后台控制器", description = "后台管理") 19 | public class ManageController extends BaseController { 20 | 21 | private static final Logger LOGGER = LoggerFactory.getLogger(ManageController.class); 22 | 23 | /** 24 | * 后台首页 25 | * @return 26 | */ 27 | @ApiOperation(value = "后台首页") 28 | @RequestMapping(value = "/index", method = RequestMethod.GET) 29 | public String index() { 30 | return "/manage/index.jsp"; 31 | } 32 | 33 | } -------------------------------------------------------------------------------- /_fixtures/grammar/java/examples/api/BookFactory.java: -------------------------------------------------------------------------------- 1 | package com.phodal.pholedge.book; 2 | 3 | import com.phodal.pholedge.book.model.Book; 4 | import com.phodal.pholedge.core.IdGenerator; 5 | import org.springframework.stereotype.Component; 6 | 7 | @Component 8 | public class BookFactory { 9 | private final IdGenerator idGenerator; 10 | 11 | public BookFactory(IdGenerator idGenerator) { 12 | this.idGenerator = idGenerator; 13 | } 14 | 15 | public Book create(String isbn, String name) { 16 | String bookId = idGenerator.generate(); 17 | return Book.create(bookId, isbn, name); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /_fixtures/grammar/java/examples/api/BookMapper.java: -------------------------------------------------------------------------------- 1 | package com.phodal.pholedge.book; 2 | 3 | import com.phodal.pholedge.book.model.Book; 4 | import com.phodal.pholedge.book.model.BookRepresentaion; 5 | import org.apache.ibatis.annotations.Mapper; 6 | import org.springframework.stereotype.Component; 7 | 8 | import java.util.List; 9 | 10 | @Component 11 | @Mapper 12 | public interface BookMapper { 13 | 14 | void doSave(Book book); 15 | 16 | List list(); 17 | 18 | Book byId(String id); 19 | } 20 | -------------------------------------------------------------------------------- /_fixtures/grammar/java/examples/api/BookRepository.java: -------------------------------------------------------------------------------- 1 | package com.phodal.pholedge.book; 2 | 3 | import com.phodal.pholedge.book.model.Book; 4 | import com.phodal.pholedge.book.model.BookRepresentaion; 5 | import com.phodal.pholedge.core.domain.Repository; 6 | import com.phodal.pholedge.core.exception.NotFoundException; 7 | import org.springframework.dao.EmptyResultDataAccessException; 8 | import org.springframework.stereotype.Component; 9 | 10 | import java.util.List; 11 | 12 | @Component 13 | public class BookRepository implements Repository { 14 | private final BookMapper bookMapper; 15 | 16 | public BookRepository(BookMapper bookMapper) { 17 | this.bookMapper = bookMapper; 18 | } 19 | 20 | public void save(Book book) { 21 | this.bookMapper.doSave(book); 22 | } 23 | 24 | public List list() { 25 | return this.bookMapper.list(); 26 | } 27 | 28 | public Book byId(String id) { 29 | try { 30 | return this.bookMapper.byId(id); 31 | } catch (EmptyResultDataAccessException e) { 32 | throw new NotFoundException(id); 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /_fixtures/grammar/java/examples/api/mapper/BookMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 10 | 13 | -------------------------------------------------------------------------------- /_fixtures/grammar/java/examples/api/model/Book.java: -------------------------------------------------------------------------------- 1 | package com.phodal.pholedge.book.model; 2 | 3 | import lombok.Builder; 4 | import lombok.Getter; 5 | 6 | import java.time.Instant; 7 | import static java.time.Instant.now; 8 | 9 | @Getter 10 | @Builder 11 | public class Book { 12 | private String id; 13 | private String isbn; 14 | private String name; 15 | private Instant createdAt; 16 | 17 | public static Book create(String id, String isbn, String name) { 18 | return Book.builder() 19 | .id(id) 20 | .isbn(isbn) 21 | .name(name) 22 | .createdAt(now()) 23 | 24 | .build(); 25 | 26 | } 27 | 28 | public BookRepresentaion toRepresentation() { 29 | return new BookRepresentaion(id, name); 30 | } 31 | 32 | public void save(String isbn, String name) { 33 | this.name = name; 34 | this.isbn = isbn; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /_fixtures/grammar/java/examples/api/model/BookRepresentaion.java: -------------------------------------------------------------------------------- 1 | package com.phodal.pholedge.book.model; 2 | 3 | import lombok.Value; 4 | 5 | @Value 6 | public class BookRepresentaion { 7 | private String id; 8 | private String name; 9 | } 10 | -------------------------------------------------------------------------------- /_fixtures/grammar/java/examples/api/model/command/CreateBookCommand.java: -------------------------------------------------------------------------------- 1 | package com.phodal.pholedge.book.model.command; 2 | 3 | import lombok.Value; 4 | 5 | import javax.validation.constraints.NotNull; 6 | 7 | @Value 8 | public class CreateBookCommand { 9 | @NotNull(message = "ISBN 不能为空") 10 | private String isbn; 11 | 12 | @NotNull(message = "书名不能为空") 13 | private String name; 14 | } 15 | -------------------------------------------------------------------------------- /_fixtures/grammar/java/examples/api/model/command/UpdateBookCommand.java: -------------------------------------------------------------------------------- 1 | package com.phodal.pholedge.book.model.command; 2 | 3 | import lombok.Value; 4 | 5 | import javax.validation.constraints.Size; 6 | 7 | @Value 8 | public class UpdateBookCommand { 9 | @Size(min = 5, message = "ISBN 长度大于 5") 10 | private String isbn; 11 | 12 | @Size(min = 1, message = "书名最小的长度大于 1") 13 | private String name; 14 | } 15 | -------------------------------------------------------------------------------- /_fixtures/grammar/java/examples/bs/DataClass.java: -------------------------------------------------------------------------------- 1 | package com.phodal.coca.analysis.identifier.model; 2 | 3 | public class DataClass { 4 | private String date; 5 | private String time; 6 | 7 | public String getDate() { 8 | return date; 9 | } 10 | 11 | public void setDate(String date) { 12 | this.date = date; 13 | } 14 | 15 | public String getTime() { 16 | return time; 17 | } 18 | 19 | public void setTime(String time) { 20 | this.time = time; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /_fixtures/grammar/java/examples/bs/MultipleIf.java: -------------------------------------------------------------------------------- 1 | class MultipleIf { 2 | public static void main(String args[]) { 3 | int i = 20; 4 | 5 | if (i == 10) 6 | System.out.println("i is 10"); 7 | else if (i == 15) 8 | System.out.println("i is 15"); 9 | else if (i == 20) 10 | System.out.println("i is 20"); 11 | if (i == 20) 12 | System.out.println("i is 20"); 13 | if (i == 20) 14 | System.out.println("i is 20"); 15 | if (i == 20) 16 | System.out.println("i is 20"); 17 | if (i == 20) 18 | System.out.println("i is 20"); 19 | if (i == 20) 20 | System.out.println("i is 20"); 21 | else 22 | System.out.println("i is not present"); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /_fixtures/grammar/java/examples/configs/move.coca: -------------------------------------------------------------------------------- 1 | wowo.a.OriginExample -> wowo.b.OriginExample 2 | wowo.b.PlaceHolder -> wowo.a.PlaceHolder -------------------------------------------------------------------------------- /_fixtures/grammar/java/examples/configs/rename.coca: -------------------------------------------------------------------------------- 1 | study.huhao.demo.infrastructure.persistence.blog.BlogPO.toDomainModel -> study.huhao.demo.infrastructure.persistence.blog.BlogPO.convertDomainModel 2 | study.huhao.demo.infrastructure.persistence.blog.BlogPO.of -> study.huhao.demo.infrastructure.persistence.blog.BlogPO.saveIt 3 | study.huhao.demo.domain.models.blog.BlogRepository.save -> study.huhao.demo.domain.models.blog.BlogRepository.saveIt -------------------------------------------------------------------------------- /_fixtures/grammar/java/examples/interface_api/BlogRepository.java: -------------------------------------------------------------------------------- 1 | package study.huhao.demo.domain.contexts.blogcontext.blog; 2 | 3 | import study.huhao.demo.domain.core.concepts.Repository; 4 | 5 | import java.util.List; 6 | import java.util.Optional; 7 | import java.util.UUID; 8 | 9 | public interface BlogRepository extends Repository { 10 | void save(Blog blog); 11 | 12 | Optional findById(UUID id); 13 | 14 | boolean existsById(UUID id); 15 | 16 | void deleteById(UUID id); 17 | 18 | List findAll(BlogCriteria criteria); 19 | 20 | @ServiceMethod(value="/hello") 21 | long count(BlogCriteria criteria); 22 | } 23 | -------------------------------------------------------------------------------- /_fixtures/grammar/java/examples/lambda/BlogPO.java: -------------------------------------------------------------------------------- 1 | package study.huhao.demo.infrastructure.persistence.blog; 2 | 3 | import study.huhao.demo.domain.models.blog.Blog; 4 | import study.huhao.demo.infrastructure.persistence.PersistenceObject; 5 | 6 | public class BlogPO implements PersistenceObject { 7 | 8 | } 9 | -------------------------------------------------------------------------------- /_fixtures/grammar/java/examples/lambda/LambdaExample.java: -------------------------------------------------------------------------------- 1 | package study.huhao.demo.infrastructure.persistence.blog; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.stereotype.Component; 5 | import study.huhao.demo.domain.core.Page; 6 | import study.huhao.demo.domain.models.blog.Blog; 7 | import study.huhao.demo.domain.models.blog.BlogCriteria; 8 | import study.huhao.demo.domain.models.blog.BlogRepository; 9 | 10 | import java.util.Optional; 11 | import java.util.UUID; 12 | 13 | import static study.huhao.demo.infrastructure.persistence.utils.PaginationUtil.buildPageRequest; 14 | 15 | @Component 16 | public class BlogRepositoryImpl implements BlogRepository { 17 | @Override 18 | public Page findAllWithPagination(BlogCriteria criteria) { 19 | var pagedBlog = blogJpaRepository.findAll(buildPageRequest(criteria)) 20 | .map(BlogPO::toDomainModel); 21 | 22 | return ""; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /_fixtures/grammar/java/examples/method-call/BlogRepositoryImpl.java: -------------------------------------------------------------------------------- 1 | package study.huhao.demo.infrastructure.persistence.blog; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.stereotype.Component; 5 | import study.huhao.demo.domain.core.Page; 6 | import study.huhao.demo.domain.models.blog.Blog; 7 | import study.huhao.demo.domain.models.blog.BlogCriteria; 8 | import study.huhao.demo.domain.models.blog.BlogRepository; 9 | 10 | import java.util.Optional; 11 | import java.util.UUID; 12 | 13 | import static java.util.stream.Collectors.toList; 14 | 15 | 16 | @Component 17 | public class BlogRepositoryImpl implements BlogRepository { 18 | @Override 19 | public void save(Blog blog) { 20 | var blogPO = BlogPO.of(blog); 21 | 22 | blogMapper.findById(blog.getId().toString()).ifPresentOrElse( 23 | po -> blogMapper.update(blogPO), 24 | () -> blogMapper.insert(blogPO) 25 | ); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /_fixtures/grammar/java/examples/move-demo/src/wowo/ImportExample.java: -------------------------------------------------------------------------------- 1 | package wowo; 2 | 3 | import wowo.b.PlaceHolder; 4 | import wowo.a.OriginExample; 5 | 6 | public class ImportExample { 7 | private PlaceHolder placeHolder; 8 | private OriginExample originExample; 9 | 10 | public ImportExample(PlaceHolder placeHolder) { 11 | this.placeHolder = placeHolder; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /_fixtures/grammar/java/examples/move-demo/src/wowo/Main.java: -------------------------------------------------------------------------------- 1 | package wowo; 2 | 3 | public class Main { 4 | public static void main(String[] args) { 5 | System.out.println("Hello World"); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /_fixtures/grammar/java/examples/move-demo/src/wowo/a/ImportForB.java: -------------------------------------------------------------------------------- 1 | package wowo.a; 2 | 3 | public class ImportForB { 4 | 5 | } 6 | -------------------------------------------------------------------------------- /_fixtures/grammar/java/examples/move-demo/src/wowo/a/OriginExample.java: -------------------------------------------------------------------------------- 1 | package wowo.a; 2 | 3 | public class OriginExample { 4 | 5 | } 6 | -------------------------------------------------------------------------------- /_fixtures/grammar/java/examples/move-demo/src/wowo/b/OriginExample.java: -------------------------------------------------------------------------------- 1 | package wowo.b; 2 | 3 | public class OriginExample { 4 | 5 | } 6 | -------------------------------------------------------------------------------- /_fixtures/grammar/java/examples/move-demo/src/wowo/b/PlaceHolder.java: -------------------------------------------------------------------------------- 1 | package wowo.b; 2 | 3 | import wowo.a.ImportForB; 4 | 5 | public class PlaceHolder { 6 | private ImportForB importForB; 7 | } 8 | -------------------------------------------------------------------------------- /_fixtures/grammar/java/examples/move-demo/src/wowo/d/IInterfaceUserExtends.java: -------------------------------------------------------------------------------- 1 | package study.huhao.demo.domain.models.blog; 2 | 3 | import study.huhao.demo.domain.core.Page; 4 | import study.huhao.demo.domain.core.Repository; 5 | 6 | import java.util.Optional; 7 | import java.util.UUID; 8 | 9 | public interface BlogRepository extends Repository { 10 | void save(Blog blog); 11 | 12 | Optional findById(UUID id); 13 | 14 | boolean existsById(UUID id); 15 | 16 | void deleteById(UUID id); 17 | 18 | Page findAllWithPagination(BlogCriteria criteria); 19 | } 20 | -------------------------------------------------------------------------------- /_fixtures/grammar/java/examples/move-demo/src/wowo/eext/ChildrenTwoFace.java: -------------------------------------------------------------------------------- 1 | package wowo.eext; 2 | 3 | import wowo.eext.sub.ChildFace; 4 | import java.util.concurrent.Future; 5 | import java.util.function.Consumer; 6 | import java.util.concurrent.ExecutionException; 7 | 8 | public class ChildrenTwoFace extends ChildFace { 9 | 10 | } 11 | -------------------------------------------------------------------------------- /_fixtures/grammar/java/examples/move-demo/src/wowo/eext/sub/BaseFace.java: -------------------------------------------------------------------------------- 1 | package wowo.eext.sub; 2 | 3 | public class BaseFace implements IBase, IFace { 4 | } 5 | -------------------------------------------------------------------------------- /_fixtures/grammar/java/examples/move-demo/src/wowo/eext/sub/ChildFace.java: -------------------------------------------------------------------------------- 1 | package wowo.eext.sub; 2 | 3 | public class ChildFace extends BaseFace { 4 | } 5 | -------------------------------------------------------------------------------- /_fixtures/grammar/java/examples/move-demo/src/wowo/eext/sub/IBase.java: -------------------------------------------------------------------------------- 1 | package wowo.eext.sub; 2 | 3 | interface IBase { 4 | } 5 | -------------------------------------------------------------------------------- /_fixtures/grammar/java/examples/move-demo/src/wowo/eext/sub/IFace.java: -------------------------------------------------------------------------------- 1 | package wowo.eext.sub; 2 | 3 | public interface IFace { 4 | 5 | } 6 | -------------------------------------------------------------------------------- /_fixtures/grammar/java/examples/poly/rename-poly.coca: -------------------------------------------------------------------------------- 1 | com.phodal.coca.analysis.JavaCallApp.parse -> com.phodal.coca.analysis.JavaCallApp.parseIt -------------------------------------------------------------------------------- /_fixtures/grammar/java/examples/sql/hello.sql: -------------------------------------------------------------------------------- 1 | SELECT name, country FROM Websites; 2 | SELECT * FROM Persons; 3 | -------------------------------------------------------------------------------- /_fixtures/grammar/java/examples/step2-Java/Main.java: -------------------------------------------------------------------------------- 1 | import gateways.FakeRouter; 2 | import domain.AggregateRootARepo; 3 | import repositories.AggregateRootA; 4 | 5 | public class Main { 6 | 7 | public static void main(String[] args) { 8 | System.out.println("main"); 9 | Router router = new FakeRouter(); 10 | AggregateRootARepo repo = new AggregateRootARepo(); 11 | repo.save(new AggregateRootA(router)); 12 | 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /_fixtures/grammar/java/examples/step2-Java/domain/AggregateRoot.java: -------------------------------------------------------------------------------- 1 | package domain; 2 | 3 | public class AggregateRoot extends Entity { 4 | 5 | 6 | } -------------------------------------------------------------------------------- /_fixtures/grammar/java/examples/step2-Java/domain/AggregateRootA.java: -------------------------------------------------------------------------------- 1 | package domain; 2 | 3 | 4 | public class AggregateRootA extends AggregateRoot { 5 | 6 | private EntityB entity_b; 7 | private ValueObjectC vo_c; 8 | private Router router; 9 | private AggregateRootB b; 10 | 11 | public AggregateRootA(Router router) { 12 | this.router = router; 13 | } 14 | public void init() { 15 | router.select(); 16 | } 17 | 18 | } -------------------------------------------------------------------------------- /_fixtures/grammar/java/examples/step2-Java/domain/AggregateRootB.java: -------------------------------------------------------------------------------- 1 | package domain; 2 | 3 | 4 | public class AggregateRootB extends AggregateRoot { 5 | 6 | private AggregateRootA a; 7 | 8 | } -------------------------------------------------------------------------------- /_fixtures/grammar/java/examples/step2-Java/domain/Entity.java: -------------------------------------------------------------------------------- 1 | package domain; 2 | 3 | 4 | public class Entity { 5 | 6 | public int id; 7 | 8 | } -------------------------------------------------------------------------------- /_fixtures/grammar/java/examples/step2-Java/domain/EntityB.java: -------------------------------------------------------------------------------- 1 | package domain; 2 | 3 | 4 | public class EntityB extends Entity { 5 | 6 | private ValueObjectD vo_d; 7 | } -------------------------------------------------------------------------------- /_fixtures/grammar/java/examples/step2-Java/domain/Provider.java: -------------------------------------------------------------------------------- 1 | package domain; 2 | 3 | 4 | public class Provider { 5 | 6 | 7 | } -------------------------------------------------------------------------------- /_fixtures/grammar/java/examples/step2-Java/domain/Router.java: -------------------------------------------------------------------------------- 1 | package domain; 2 | 3 | 4 | public class Router extends Provider { 5 | 6 | public int select() { 7 | return 0; 8 | } 9 | 10 | } -------------------------------------------------------------------------------- /_fixtures/grammar/java/examples/step2-Java/domain/ValueObject.java: -------------------------------------------------------------------------------- 1 | package domain; 2 | 3 | 4 | public class ValueObject { 5 | 6 | 7 | } -------------------------------------------------------------------------------- /_fixtures/grammar/java/examples/step2-Java/domain/ValueObjectC.java: -------------------------------------------------------------------------------- 1 | package domain; 2 | 3 | 4 | public class ValueObjectC extends ValueObject { 5 | 6 | 7 | } -------------------------------------------------------------------------------- /_fixtures/grammar/java/examples/step2-Java/domain/ValueObjectD.java: -------------------------------------------------------------------------------- 1 | package domain; 2 | 3 | 4 | public class ValueObjectD extends ValueObject { 5 | 6 | 7 | } -------------------------------------------------------------------------------- /_fixtures/grammar/java/examples/step2-Java/gateways/FakeRouter.java: -------------------------------------------------------------------------------- 1 | package gateways; 2 | 3 | import domain.Router; 4 | 5 | public class FakeRouter extends Router { 6 | public int select(){ 7 | System.out.println("routed \n"); 8 | return 1; 9 | }; 10 | } -------------------------------------------------------------------------------- /_fixtures/grammar/java/examples/step2-Java/repositories/AggregateRootARepo.java: -------------------------------------------------------------------------------- 1 | package repositories; 2 | 3 | import domain.AggregateRootA; 4 | 5 | 6 | public class AggregateRootARepo extends Repository { 7 | private AggregateRootA[] arList; 8 | public void save(AggregateRootA a){ 9 | System.out.println("saved\n"); 10 | }; 11 | } -------------------------------------------------------------------------------- /_fixtures/grammar/java/examples/step2-Java/repositories/Repository.java: -------------------------------------------------------------------------------- 1 | package repositories; 2 | 3 | public class Repository { 4 | 5 | } -------------------------------------------------------------------------------- /_fixtures/grammar/java/interface/BlogRepository.java: -------------------------------------------------------------------------------- 1 | package study.huhao.demo.domain.contexts.blogcontext.blog; 2 | 3 | import study.huhao.demo.domain.core.concepts.Repository; 4 | 5 | import java.util.List; 6 | import java.util.Optional; 7 | import java.util.UUID; 8 | 9 | public interface BlogRepository extends Repository { 10 | void save(Blog blog); 11 | 12 | Optional findById(UUID id); 13 | 14 | boolean existsById(UUID id); 15 | 16 | void deleteById(UUID id); 17 | 18 | List findAll(BlogCriteria criteria); 19 | 20 | @ServiceMethod(value="/hello") 21 | long count(BlogCriteria criteria); 22 | } 23 | -------------------------------------------------------------------------------- /_fixtures/grammar/java/lambda/BlogRepositoryImpl.java: -------------------------------------------------------------------------------- 1 | package study.huhao.demo.adapters.outbound.persistence.blog; 2 | 3 | import org.springframework.stereotype.Repository; 4 | import study.huhao.demo.domain.contexts.blogcontext.blog.Blog; 5 | import study.huhao.demo.domain.contexts.blogcontext.blog.BlogCriteria; 6 | import study.huhao.demo.domain.contexts.blogcontext.blog.BlogRepository; 7 | 8 | import java.util.List; 9 | import java.util.Optional; 10 | import java.util.UUID; 11 | 12 | import static java.util.stream.Collectors.toList; 13 | 14 | 15 | @Repository 16 | public class BlogRepositoryImpl implements BlogRepository { 17 | 18 | private final BlogMapper blogMapper; 19 | 20 | @Override 21 | public void save(Blog blog) { 22 | var blogPO = BlogPO.of(blog); 23 | 24 | blogMapper.findById(blog.getId().toString()).ifPresentOrElse( 25 | po -> blogMapper.update(blogPO), 26 | () -> blogMapper.insert(blogPO) 27 | ); 28 | } 29 | 30 | @Override 31 | public Optional findById(UUID id) { 32 | return blogMapper.findById(id.toString()).map(BlogPO::toDomainModel); 33 | } 34 | } 35 | 36 | -------------------------------------------------------------------------------- /_fixtures/grammar/java/regression/BuilderCallSplitIssue.java: -------------------------------------------------------------------------------- 1 | package com.phodal.coca.bug; 2 | 3 | import static org.assertj.core.api.Assertions.assertThat; 4 | import org.springframework.web.context.support.AnnotationConfigWebApplicationContext; 5 | 6 | public class BuilderCallSplitIssue { 7 | void someAssert() { 8 | AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(); 9 | 10 | assertThat(ctx.containsBean(TRANSITIVE_BEAN_NAME)).isFalse(); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /_fixtures/grammar/java/regression/DoubleClass.java: -------------------------------------------------------------------------------- 1 | package com.phodal.coca.abug; 2 | 3 | public class ClassOne extends HasStatic { 4 | static final int x = 3; 5 | static int y = 4; 6 | public static void pr() { 7 | 8 | } 9 | } 10 | 11 | public class ClassTwo { 12 | final int z=10; 13 | 14 | public static void main(String[] args) { 15 | Outer outer = new Outer(); 16 | System.out.println(outer.new Inner().y); 17 | } 18 | } -------------------------------------------------------------------------------- /_fixtures/grammar/java/regression/DummyActivity.java: -------------------------------------------------------------------------------- 1 | package com.example; 2 | 3 | import android.app.Activity; 4 | 5 | public class DummyActivity extends Activity { 6 | } 7 | -------------------------------------------------------------------------------- /_fixtures/grammar/java/regression/FormalParameterCall.java: -------------------------------------------------------------------------------- 1 | package regression; 2 | 3 | import hello.CreateBookCommand; 4 | 5 | @Component 6 | public class BookService implements Service { 7 | @Transactional 8 | public void getIsbnId(CreateBookCommand command) { 9 | command.getIsbn(); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /_fixtures/grammar/java/regression/HostDependentDownloadableContribution.java: -------------------------------------------------------------------------------- 1 | package cc.arduino.packages.contributions; 2 | 3 | import org.junit.Test; 4 | import processing.app.Platform; 5 | 6 | import static org.junit.Assert.assertFalse; 7 | import static org.junit.Assert.assertTrue; 8 | 9 | public class HostDependentDownloadableContribution{ 10 | 11 | public void macOsXPositiveTest() { 12 | HostDependentDownloadableContributionStub contribution = new HostDependentDownloadableContributionStub() { 13 | @Override 14 | public String getHost() { 15 | return "x86_64-apple-darwin"; 16 | } 17 | }; 18 | 19 | Platform platform = new Platform() { 20 | @Override 21 | public String getOsName() { 22 | return "Mac OS X"; 23 | } 24 | 25 | @Override 26 | public String getOsArch() { 27 | return "x86_64"; 28 | } 29 | }; 30 | } 31 | } -------------------------------------------------------------------------------- /_fixtures/grammar/java/regression/InnerClass.java: -------------------------------------------------------------------------------- 1 | package com.phodal.coca.abug; 2 | 3 | public class Outer { 4 | final int z=10; 5 | 6 | class Inner extends HasStatic { 7 | static final int x = 3; 8 | static int y = 4; 9 | public static void pr() { 10 | 11 | } 12 | } 13 | 14 | public static void main(String[] args) { 15 | Outer outer = new Outer(); 16 | System.out.println(outer.new Inner().y); 17 | } 18 | } -------------------------------------------------------------------------------- /_fixtures/grammar/java/regression/JavaInner.java: -------------------------------------------------------------------------------- 1 | public class Outer { 2 | final int z=10; 3 | 4 | class Inner extends HasStatic { 5 | static final int x = 3; 6 | static int y = 4; 7 | public static void pr() { 8 | 9 | } 10 | } 11 | 12 | public static void main(String[] args) { 13 | Outer outer = new Outer(); 14 | System.out.println(outer.new Inner().y); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /_fixtures/grammar/java/regression/NormalChainCall.java: -------------------------------------------------------------------------------- 1 | package hello.outer; 2 | 3 | import org.springframework.web.util.UriComponents; 4 | import org.springframework.web.util.UriComponentsBuilder; 5 | 6 | public class PublishedBlogResource { 7 | public ResponseEntity post(UriComponentsBuilder uriComponentsBuilder) { 8 | UriComponents uriComponents = uriComponentsBuilder.path("/published-blog/{id}").buildAndExpand("1234"); 9 | // return uriComponents.toUri(); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /_fixtures/grammar/python/blog_entity.py: -------------------------------------------------------------------------------- 1 | from ddd.shared.domain_model import DomainModel 2 | 3 | 4 | class Blog(object): 5 | def __init__(self, id, title, content): 6 | self.id = id 7 | self.title = title 8 | self.content = content 9 | 10 | @classmethod 11 | def from_dict(cls, adict): 12 | blog = Blog( 13 | id=adict['id'], 14 | title=adict['title'], 15 | content=adict['content'], 16 | ) 17 | 18 | return blog 19 | 20 | def to_dict(self): 21 | return { 22 | 'id': self.id, 23 | 'title': self.title, 24 | 'content': self.content, 25 | } 26 | 27 | def __eq__(self, other): 28 | return self.to_dict() == other.to_dict() 29 | 30 | DomainModel.register(Blog) 31 | -------------------------------------------------------------------------------- /_fixtures/grammar/sql/BookMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 10 | 13 | -------------------------------------------------------------------------------- /_fixtures/grammar/sql/hello.sql: -------------------------------------------------------------------------------- 1 | SELECT name, country FROM Websites; 2 | SELECT * FROM Persons; 3 | -------------------------------------------------------------------------------- /_fixtures/grammar/typescript/Class.ts: -------------------------------------------------------------------------------- 1 | interface IPerson { 2 | name: string; 3 | } 4 | 5 | class Person implements IPerson { 6 | public publicString: string; 7 | private privateString: string; 8 | protected protectedString: string; 9 | readonly readonlyString: string; 10 | name: string; 11 | 12 | constructor(name: string) { 13 | this.name = name; 14 | } 15 | } 16 | 17 | class Employee extends Person { 18 | empCode: number; 19 | static pi: number = 3.14; 20 | 21 | constructor(empcode: number, name:string) { 22 | super(name); 23 | this.empCode = empcode; 24 | } 25 | 26 | displayName():void { 27 | console.log("Name = " + this.name + ", Employee Code = " + this.empCode); 28 | } 29 | } 30 | 31 | let emp = new Employee(100,"Steve"); -------------------------------------------------------------------------------- /_fixtures/refactor/move.config: -------------------------------------------------------------------------------- 1 | move.a.ImportForB -> move.b.ImportForB 2 | -------------------------------------------------------------------------------- /_fixtures/refactor/move/a/ImportForB.java: -------------------------------------------------------------------------------- 1 | package move.a; 2 | 3 | public class ImportForB { 4 | 5 | } 6 | -------------------------------------------------------------------------------- /_fixtures/refactor/move/b/OriginExample.java: -------------------------------------------------------------------------------- 1 | package move.b; 2 | 3 | public class OriginExample { 4 | 5 | } 6 | -------------------------------------------------------------------------------- /_fixtures/refactor/move/grammar/BlogRepository.java: -------------------------------------------------------------------------------- 1 | package study.huhao.demo.domain.contexts.blogcontext.blog; 2 | 3 | import study.huhao.demo.domain.core.concepts.Repository; 4 | 5 | import java.util.List; 6 | import java.util.Optional; 7 | import java.util.UUID; 8 | 9 | public interface BlogRepository extends Repository { 10 | void save(Blog blog); 11 | 12 | Optional findById(UUID id); 13 | 14 | boolean existsById(UUID id); 15 | 16 | void deleteById(UUID id); 17 | 18 | List findAll(BlogCriteria criteria); 19 | 20 | @ServiceMethod(value="/hello") 21 | long count(BlogCriteria criteria); 22 | } 23 | -------------------------------------------------------------------------------- /_fixtures/refactor/move/grammar/BookRepository.java: -------------------------------------------------------------------------------- 1 | package com.phodal.pholedge.book; 2 | 3 | import com.phodal.pholedge.book.model.Book; 4 | import com.phodal.pholedge.book.model.BookRepresentaion; 5 | import com.phodal.pholedge.core.domain.Repository; 6 | import com.phodal.pholedge.core.exception.NotFoundException; 7 | import org.springframework.dao.EmptyResultDataAccessException; 8 | import org.springframework.stereotype.Component; 9 | 10 | import java.util.List; 11 | 12 | @Component 13 | public class BookRepository implements Repository { 14 | private final BookMapper bookMapper; 15 | 16 | public BookRepository(BookMapper bookMapper) { 17 | this.bookMapper = bookMapper; 18 | } 19 | 20 | public void save(Book book) { 21 | this.bookMapper.doSave(book); 22 | } 23 | 24 | public List list() { 25 | return this.bookMapper.list(); 26 | } 27 | 28 | public Book byId(String id) { 29 | try { 30 | return this.bookMapper.byId(id); 31 | } catch (EmptyResultDataAccessException e) { 32 | throw new NotFoundException(id); 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /_fixtures/refactor/rename.config: -------------------------------------------------------------------------------- 1 | polymorphism.Overload.demoA -> polymorphism.Overload.demo 2 | -------------------------------------------------------------------------------- /_fixtures/refactor/rename_back.config: -------------------------------------------------------------------------------- 1 | polymorphism.Overload.demoA -> polymorphism.Overload.demo 2 | -------------------------------------------------------------------------------- /_fixtures/refactor/unused/Overload.java: -------------------------------------------------------------------------------- 1 | package polymorphism; 2 | 3 | import java.util.List; 4 | import java.util.Optional; 5 | import java.util.UUID; 6 | 7 | public class Overload { 8 | void demoA(int a) { 9 | System.out.println("a: " + a); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /_fixtures/suggest/builder/Bee.java: -------------------------------------------------------------------------------- 1 | package builder; 2 | 3 | public class BeeBuilder extends Insect { 4 | public BeeBuilder(int size) { 5 | super(size); 6 | System.out.println("Constructor: BeeBuilder size"); 7 | } 8 | 9 | public BeeBuilder(int size, int height) { 10 | super(size, height); 11 | System.out.println("Constructor: BeeBuilder size, height"); 12 | } 13 | 14 | public BeeBuilder(int size, int height, String color) { 15 | super(size, height); 16 | System.out.println("Constructor: BeeBuilder size, height, color"); 17 | } 18 | 19 | public BeeBuilder(int size, int height, String color, int x, int y, int z) { 20 | super(size, height); 21 | System.out.println("Constructor: BeeBuilder size, height, color"); 22 | } 23 | } -------------------------------------------------------------------------------- /_fixtures/suggest/polymorphism/Overload.java: -------------------------------------------------------------------------------- 1 | package polymorphism; 2 | 3 | public class Overload { 4 | void demo(int a) { 5 | System.out.println("a: " + a); 6 | } 7 | 8 | void demo(int a, int b) { 9 | System.out.println("a and b: " + a + "," + b); 10 | } 11 | 12 | double demo(double a) { 13 | System.out.println("double a: " + a); 14 | return a * a; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /_fixtures/suggest/static/StaticMain.java: -------------------------------------------------------------------------------- 1 | class Main { 2 | public static void main(String args[]) { 3 | 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /_fixtures/tbs/demo-tbs-java-project/src/main/java/tbs/Calculate.java: -------------------------------------------------------------------------------- 1 | package tbs; 2 | 3 | public class Calculate { 4 | public int add(int i, int i1) { 5 | return i + i1; 6 | } 7 | 8 | public int sub(int i, int i1) { 9 | return i - i1; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /_fixtures/tbs/demo-tbs-java-project/src/main/java/tbs/XmlSanitizer.java: -------------------------------------------------------------------------------- 1 | package tbs; 2 | 3 | import java.util.regex.Pattern; 4 | 5 | /** 6 | * Replaces critical characters in xml files 7 | */ 8 | public final class XmlSanitizer { 9 | 10 | private static final Pattern PURE_ASCII_STRING = Pattern.compile("^\\p{ASCII}*$"); // "[^\\p{ASCII}]+" 11 | 12 | /** 13 | * Checks if string contains &, <, >, ", ', non-ascii characters or anything other than A-Z, 0-9 14 | * 15 | * @param test String to test 16 | * @return true, if string only contains valid chars 17 | */ 18 | public static boolean isValid(final String test) { 19 | // check we don't have xml chars in it 20 | boolean result = !test.contains("&") && !test.contains("<") && !test.contains(">") && !test.contains("\"") && !test.contains("'"); 21 | // assure we only have ASCII chars 22 | result = result && PURE_ASCII_STRING.matcher(test).matches(); 23 | // assure we really only A-Z and numbers in it 24 | result = result && (test.replaceAll("[^a-zA-Z0-9-+.!_\\s]", "").length() == test.length()); 25 | return result; 26 | } 27 | 28 | private XmlSanitizer() { 29 | 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /_fixtures/tbs/demo-tbs-java-project/src/test/java/tbs/AssertionRoulette.java: -------------------------------------------------------------------------------- 1 | package tbs; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.assertEquals; 6 | import static org.junit.Assert.assertThat; 7 | 8 | public class AssertionRoulette { 9 | @Test 10 | public void testCloneNonBareRepoFromLocalTestServer() throws Exception { 11 | Calculate calculate = new Calculate(); 12 | int result = calculate.add(7, 8); 13 | int success = 15; 14 | assertEquals(success, result); 15 | 16 | int subResult = calculate.sub(9, 2); 17 | int subSuccess = 7; 18 | assertEquals(subSuccess, subResult); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /_fixtures/tbs/demo-tbs-java-project/src/test/java/tbs/ConditionalTest.java: -------------------------------------------------------------------------------- 1 | package tbs; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.assertEquals; 6 | 7 | public class ConditionalTest { 8 | @Test 9 | public void byGod() { 10 | Calculate calculate = new Calculate(); 11 | // just examples 12 | if (calculate.add(7, 9) == 16) { 13 | if (calculate.sub(12, 9) == 3) { 14 | int subSuccess = 7; 15 | assertEquals(subSuccess, calculate.sub(9, 2)); 16 | } 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /_fixtures/tbs/demo-tbs-java-project/src/test/java/tbs/ConstructorInitialization.java: -------------------------------------------------------------------------------- 1 | package tbs; 2 | 3 | import org.junit.Before; 4 | import org.junit.Test; 5 | 6 | import static org.junit.Assert.assertEquals; 7 | 8 | public class ConstructorInitialization { 9 | @Before 10 | public void init() throws Exception { 11 | 12 | } 13 | 14 | @Test 15 | public void name() { 16 | Calculate calculate = new Calculate(); 17 | int result = calculate.add(7, 8); 18 | int success = 15; 19 | assertEquals(success, result); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /_fixtures/tbs/demo-tbs-java-project/src/test/java/tbs/DuplicateAssert.java: -------------------------------------------------------------------------------- 1 | package tbs; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.assertEquals; 6 | 7 | public class DuplicateAssert { 8 | @Test 9 | public void testXmlSanitizer() { 10 | boolean valid = XmlSanitizer.isValid("Fritzbox"); 11 | assertEquals("Fritzbox is valid", true, valid); 12 | 13 | valid = XmlSanitizer.isValid("Fritz Box"); 14 | assertEquals("Spaces are valid", true, valid); 15 | 16 | valid = XmlSanitizer.isValid("Frützbüx"); 17 | assertEquals("Frützbüx is invalid", false, valid); 18 | 19 | valid = XmlSanitizer.isValid("Fritz!box"); 20 | assertEquals("Exclamation mark is valid", true, valid); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /_fixtures/tbs/demo-tbs-java-project/src/test/java/tbs/EmptyTest.java: -------------------------------------------------------------------------------- 1 | package tbs; 2 | 3 | import org.junit.Test; 4 | 5 | public class EmptyTest { 6 | 7 | @Test 8 | public void testCredGetFullSampleV1() throws Throwable { 9 | // ScrapedCredentials credentials = innerCredTest(FULL_SAMPLE_v1); 10 | // assertEquals("p4ssw0rd", credentials.pass); 11 | // assertEquals("user@example.com",credentials.user); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /_fixtures/tbs/demo-tbs-java-project/src/test/java/tbs/IgnoreTest.java: -------------------------------------------------------------------------------- 1 | package tbs; 2 | 3 | import org.junit.Ignore; 4 | 5 | public class IgnoreTest { 6 | @Ignore("Oops, Not Time fix it") 7 | public void peerPriority() throws Exception { 8 | 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /_fixtures/tbs/demo-tbs-java-project/src/test/java/tbs/MagicNumberTest.java: -------------------------------------------------------------------------------- 1 | package tbs; 2 | 3 | import org.junit.Test; 4 | 5 | import java.util.Calendar; 6 | 7 | import static org.junit.Assert.assertEquals; 8 | 9 | public class MagicNumberTest { 10 | @Test 11 | public void testGetLocalTimeAsCalendar() { 12 | int result = 7 + 8; 13 | assertEquals(15, result); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /_fixtures/tbs/demo-tbs-java-project/src/test/java/tbs/MysteryGuest.java: -------------------------------------------------------------------------------- 1 | package tbs; 2 | 3 | import org.junit.Test; 4 | 5 | import java.io.FileNotFoundException; 6 | import java.io.FileOutputStream; 7 | import java.io.IOException; 8 | 9 | public class MysteryGuest { 10 | @Test 11 | public void testPersistence() throws Exception { 12 | try (FileOutputStream out = new FileOutputStream("people.bin");) { 13 | int result = 5; 14 | out.write(result); 15 | } catch (FileNotFoundException e) { 16 | // blabla 17 | } catch (IOException e) { 18 | // blabla 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /_fixtures/tbs/demo-tbs-java-project/src/test/java/tbs/RedundantAssertionTest.java: -------------------------------------------------------------------------------- 1 | package tbs; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.assertEquals; 6 | 7 | public class RedundantAssertionTest { 8 | @Test 9 | public void testTrue() { 10 | assertEquals(true, true); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /_fixtures/tbs/demo-tbs-java-project/src/test/java/tbs/RedundantPrint.java: -------------------------------------------------------------------------------- 1 | package tbs; 2 | 3 | import org.junit.Test; 4 | 5 | public class RedundantPrint { 6 | @Test 7 | public void testTransform10mNEUAndBack() { 8 | String result = "a, b, c"; 9 | System.out.println("result = " + result); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /_fixtures/tbs/demo-tbs-java-project/src/test/java/tbs/SleepyTest.java: -------------------------------------------------------------------------------- 1 | package tbs; 2 | 3 | import org.junit.Test; 4 | 5 | public class SleepyTest { 6 | @Test 7 | public void testEdictExternSearch() throws Exception { 8 | Thread.sleep(500); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /_fixtures/tbs/demo-tbs-java-project/src/test/java/tbs/UnknownTest.java: -------------------------------------------------------------------------------- 1 | package tbs; 2 | 3 | import org.junit.Test; 4 | 5 | public class UnknownTest { 6 | @Test 7 | public void hitGetPOICategoriesApi() throws Exception { 8 | String a = "blabla"; 9 | String b = "blablac"; 10 | String c = a + b; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /_fixtures/tbs/regression/CreatorNotUnknownTest.java: -------------------------------------------------------------------------------- 1 | package cc.arduino.packages.contributions; 2 | 3 | import org.junit.Test; 4 | import processing.app.Platform; 5 | 6 | import static org.junit.Assert.assertFalse; 7 | import static org.junit.Assert.assertTrue; 8 | 9 | public class HostDependentDownloadableContributionTest { 10 | @Test 11 | public void macOsXPositiveTest() { 12 | HostDependentDownloadableContributionStub contribution = new HostDependentDownloadableContributionStub() { 13 | @Override 14 | public String getHost() { 15 | return "x86_64-apple-darwin"; 16 | } 17 | }; 18 | 19 | Platform platform = new Platform() { 20 | @Override 21 | public String getOsName() { 22 | return "Mac OS X"; 23 | } 24 | 25 | @Override 26 | public String getOsArch() { 27 | return "x86_64"; 28 | } 29 | }; 30 | 31 | assertTrue(contribution.isCompatible(platform)); 32 | } 33 | } -------------------------------------------------------------------------------- /_fixtures/tbs/usecases/AssertionRouletteTest.java: -------------------------------------------------------------------------------- 1 | package tbs; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.assertEquals; 6 | import static org.junit.Assert.assertThat; 7 | 8 | public class AssertionRouletteTest { 9 | @Test 10 | public void testCloneNonBareRepoFromLocalTestServer() throws Exception { 11 | Calculate calculate = new Calculate(); 12 | int result = calculate.add(7, 8); 13 | int success = 15; 14 | assertEquals(success, result); 15 | 16 | int subResult = calculate.sub(9, 2); 17 | int subSuccess = 7; 18 | assertEquals(subSuccess, subResult); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /_fixtures/tbs/usecases/ConditionalTest.java: -------------------------------------------------------------------------------- 1 | package tbs; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.assertEquals; 6 | 7 | public class ConditionalTest { 8 | @Test 9 | public void byGod() { 10 | Calculate calculate = new Calculate(); 11 | // just examples 12 | if (calculate.add(7, 9) == 16) { 13 | if (calculate.sub(12, 9) == 3) { 14 | int subSuccess = 7; 15 | assertEquals(subSuccess, calculate.sub(9, 2)); 16 | } 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /_fixtures/tbs/usecases/ConstructorInitializationTest.java: -------------------------------------------------------------------------------- 1 | package tbs; 2 | 3 | import org.junit.Before; 4 | import org.junit.Test; 5 | 6 | import static org.junit.Assert.assertEquals; 7 | 8 | public class ConstructorInitializationTest { 9 | @Before 10 | public void init() throws Exception { 11 | 12 | } 13 | 14 | @Test 15 | public void name() { 16 | Calculate calculate = new Calculate(); 17 | int result = calculate.add(7, 8); 18 | int success = 15; 19 | assertEquals(success, result); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /_fixtures/tbs/usecases/DuplicateAssertTest.java: -------------------------------------------------------------------------------- 1 | package tbs; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.assertEquals; 6 | 7 | public class DuplicateAssertTest { 8 | @Test 9 | public void testXmlSanitizer() { 10 | boolean valid = XmlSanitizer.isValid("Fritzbox"); 11 | assertEquals("Fritzbox is valid", true, valid); 12 | 13 | valid = XmlSanitizer.isValid("Fritz Box"); 14 | assertEquals("Spaces are valid", true, valid); 15 | 16 | valid = XmlSanitizer.isValid("Frützbüx"); 17 | assertEquals("Frützbüx is invalid", false, valid); 18 | 19 | valid = XmlSanitizer.isValid("Fritz!box"); 20 | assertEquals("Exclamation mark is valid", true, valid); 21 | 22 | valid = XmlSanitizer.isValid("Fritz!box"); 23 | assertEquals("Exclamation mark is valid", true, valid); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /_fixtures/tbs/usecases/EmptyTest.java: -------------------------------------------------------------------------------- 1 | package tbs; 2 | 3 | import org.junit.Test; 4 | 5 | public class EmptyTest { 6 | 7 | @Test 8 | public void testCredGetFullSampleV1() throws Throwable { 9 | // ScrapedCredentials credentials = innerCredTest(FULL_SAMPLE_v1); 10 | // assertEquals("p4ssw0rd", credentials.pass); 11 | // assertEquals("user@example.com",credentials.user); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /_fixtures/tbs/usecases/IgnoreTest.java: -------------------------------------------------------------------------------- 1 | package tbs; 2 | 3 | import org.junit.Ignore; 4 | 5 | public class IgnoreTest { 6 | @Ignore("Oops, Not Time fix it") 7 | public void peerPriority() throws Exception { 8 | 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /_fixtures/tbs/usecases/MagicNumberTest.java: -------------------------------------------------------------------------------- 1 | package tbs; 2 | 3 | import org.junit.Test; 4 | 5 | import java.util.Calendar; 6 | 7 | import static org.junit.Assert.assertEquals; 8 | 9 | public class MagicNumberTest { 10 | @Test 11 | public void testGetLocalTimeAsCalendar() { 12 | int result = 7 + 8; 13 | assertEquals(15, result); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /_fixtures/tbs/usecases/MysteryGuestTest.java: -------------------------------------------------------------------------------- 1 | package tbs; 2 | 3 | import org.junit.Test; 4 | 5 | import java.io.FileNotFoundException; 6 | import java.io.FileOutputStream; 7 | import java.io.IOException; 8 | 9 | public class MysteryGuestTest { 10 | @Test 11 | public void testPersistence() throws Exception { 12 | try (FileOutputStream out = new FileOutputStream("people.bin");) { 13 | int result = 5; 14 | out.write(result); 15 | } catch (FileNotFoundException e) { 16 | // blabla 17 | } catch (IOException e) { 18 | // blabla 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /_fixtures/tbs/usecases/RedundantAssertionTest.java: -------------------------------------------------------------------------------- 1 | package tbs; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.assertEquals; 6 | 7 | public class RedundantAssertionTest { 8 | @Test 9 | public void testTrue() { 10 | Calculate calculate = new Calculate(); 11 | int result = calculate.add(7, 8); 12 | int success = 15; 13 | 14 | assertEquals(true, true); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /_fixtures/tbs/usecases/RedundantPrintTest.java: -------------------------------------------------------------------------------- 1 | package tbs; 2 | 3 | import org.junit.Test; 4 | 5 | public class RedundantPrintTest { 6 | @Test 7 | public void testTransform10mNEUAndBack() { 8 | String result = "a, b, c"; 9 | System.out.println("result = " + result); 10 | assertEquals(true, true); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /_fixtures/tbs/usecases/SleepyTest.java: -------------------------------------------------------------------------------- 1 | package tbs; 2 | 3 | import org.junit.Test; 4 | 5 | public class SleepyTest { 6 | @Test 7 | public void testEdictExternSearch() throws Exception { 8 | Thread.sleep(500); 9 | assertEquals(true, true); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /_fixtures/tbs/usecases/TestersOnly.java: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * public for test call only 4 | * 5 | */ 6 | -------------------------------------------------------------------------------- /_fixtures/tbs/usecases/UnknownTest.java: -------------------------------------------------------------------------------- 1 | package tbs; 2 | 3 | import org.junit.Test; 4 | 5 | public class UnknownTest { 6 | @Test 7 | public void hitGetPOICategoriesApi() throws Exception { 8 | String a = "blabla"; 9 | String b = "blablac"; 10 | String c = a + b; 11 | Show(a, b); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /_fixtures/todo/Todo.go: -------------------------------------------------------------------------------- 1 | package todo 2 | 3 | //todo: add todo test for golang 4 | -------------------------------------------------------------------------------- /_fixtures/todo/Todo.java: -------------------------------------------------------------------------------- 1 | package todo; 2 | 3 | public class Todo { 4 | private Long id; 5 | 6 | /* todo update 7 | * 8 | */ 9 | public Long getId() { 10 | return id; 11 | } 12 | 13 | // Todo(phodal) : add more content 14 | public void setId(Long id) { 15 | this.id = id; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /_fixtures/todo/todo.phodal: -------------------------------------------------------------------------------- 1 | // todo: add todo for other text like phodal 2 | -------------------------------------------------------------------------------- /_fixtures/todo/todo.py: -------------------------------------------------------------------------------- 1 | # todo: add todo for python -------------------------------------------------------------------------------- /_fixtures/ts/grammar/AbstractClass.ts: -------------------------------------------------------------------------------- 1 | abstract class Person { 2 | name: string; 3 | 4 | constructor(name: string) { 5 | this.name = name; 6 | } 7 | 8 | abstract find(string): Person; 9 | abstract nameAbs: string; 10 | } 11 | 12 | class Employee extends Person { 13 | empCode: number; 14 | 15 | constructor(name: string, code: number) { 16 | super(name); // must call super() 17 | this.empCode = code; 18 | } 19 | 20 | find(name:string): Person { 21 | // execute AJAX request to find an employee from a db 22 | return new Employee(name, 1); 23 | } 24 | } 25 | 26 | let emp: Person = new Employee("James", 100); 27 | emp.display(); //James 28 | 29 | let emp2: Person = emp.find('Steve'); -------------------------------------------------------------------------------- /_fixtures/ts/grammar/Class.ts: -------------------------------------------------------------------------------- 1 | interface IPerson { 2 | name: string; 3 | } 4 | 5 | class Person implements IPerson { 6 | public publicString: string; 7 | private privateString: string; 8 | protected protectedString: string; 9 | readonly readonlyString: string; 10 | name: string; 11 | 12 | constructor(name: string) { 13 | this.name = name; 14 | } 15 | } 16 | 17 | class Employee extends Person { 18 | empCode: number; 19 | static pi: number = 3.14; 20 | 21 | constructor(empcode: number, name:string) { 22 | super(name); 23 | this.empCode = empcode; 24 | } 25 | 26 | displayName():void { 27 | console.log("Name = " + this.name + ", Employee Code = " + this.empCode); 28 | } 29 | } 30 | 31 | let emp = new Employee(100,"Steve"); -------------------------------------------------------------------------------- /_fixtures/ts/grammar/Export.ts: -------------------------------------------------------------------------------- 1 | namespace StringUtility 2 | { 3 | function ToCapital(str: string): string { 4 | return str.toUpperCase(); 5 | } 6 | 7 | function Nemw(str: string, length: number = 0): string { 8 | return str.toUpperCase(); 9 | } 10 | export function Eported(from: string, length: number = 0): string { 11 | return from.toUpperCase(); 12 | } 13 | 14 | export function Eported2(str: string, length: number = 0): string { 15 | return str.toUpperCase(); 16 | } 17 | } -------------------------------------------------------------------------------- /_fixtures/ts/grammar/Function.ts: -------------------------------------------------------------------------------- 1 | function Sum(x: number, y: number) : void { 2 | console.log('processNumKeyPairs: key = ' + key + ', value = ' + value) 3 | return x + y; 4 | } 5 | 6 | 7 | let greeting = function() { 8 | console.log("Hello TypeScript!"); 9 | }; 10 | 11 | let SumAnon = function(x: number, y: number) : number 12 | { 13 | return x + y; 14 | } 15 | 16 | function Greet(greeting: string, name?: string ) : string { 17 | return greeting + ' ' + name + '!'; 18 | } 19 | 20 | function Greet2(name: string, greeting: string = "Hello") : string { 21 | return greeting + ' ' + name + '!'; 22 | } 23 | 24 | Greet(undefined, 'Steve'); 25 | 26 | let sumArrow = (x: number, y: number): number => { 27 | return x + y 28 | } 29 | 30 | let Print = () => console.log("Hello TypeScript"); 31 | 32 | let sumShortArrow = (x: number, y: number) => x + y; 33 | 34 | function Greet(greeting: string, ...names: string[]) { 35 | return greeting + " " + names.join(", ") + "!"; 36 | } 37 | 38 | 39 | function Test(value: TestClass | TestClass2): value is TestClass { 40 | return (value).someFunction !== undefined; 41 | } -------------------------------------------------------------------------------- /_fixtures/ts/grammar/Generic.ts: -------------------------------------------------------------------------------- 1 | function getArray(items : T[] ) : T[] { 2 | return new Array().concat(); 3 | } 4 | 5 | let myNumArr = getArray([100, 200, 300]); 6 | let myStrArr = getArray(["Hello", "World"]); 7 | 8 | myNumArr.push(400); // OK 9 | myStrArr.push("Hello TypeScript"); // OK 10 | 11 | myNumArr.push("Hi"); // Compiler Error 12 | myStrArr.push(500); // Compiler Error 13 | 14 | 15 | function displayType(id:T, name:U): void { 16 | console.log(typeof(id) + ", " + typeof(name)); 17 | } 18 | 19 | function displayTypeNon(id:T, name:string): void { 20 | console.log(typeof(id) + ", " + typeof(name)); 21 | } 22 | 23 | function displayNames(names:T[]): void { 24 | console.log(names.join(", ")); 25 | } 26 | 27 | 28 | function display(per: T): void { 29 | console.log(`${ per.firstName} ${per.lastName}` ); 30 | } -------------------------------------------------------------------------------- /_fixtures/ts/grammar/GenericClass.ts: -------------------------------------------------------------------------------- 1 | class KeyValuePair 2 | { 3 | private key: T; 4 | private val: U; 5 | 6 | setKeyValue(key: T, val: U): void { 7 | this.key = key; 8 | this.val = val; 9 | } 10 | 11 | display():void { 12 | console.log(`Key = ${this.key}, val = ${this.val}`); 13 | } 14 | } 15 | let kvp1 = new KeyValuePair(); 16 | kvp1.setKeyValue(1, "Steve"); 17 | kvp1.display(); //Output: Key = 1, Val = Steve 18 | 19 | let kvp2 = new KayValuePair(); 20 | kvp2.SetKeyValue("CEO", "Bill"); 21 | kvp2.display(); //Output: Key = CEO, Val = Bill 22 | 23 | 24 | interface IKeyValueProcessor 25 | { 26 | process(key: T, val: U): void; 27 | }; 28 | 29 | class kvProcessor implements IKeyValueProcessor 30 | { 31 | process(key:T, val:U):void { 32 | console.log(`Key = ${key}, val = ${val}`); 33 | } 34 | } -------------------------------------------------------------------------------- /_fixtures/ts/grammar/GenericInterface.ts: -------------------------------------------------------------------------------- 1 | interface IProcessor 2 | { 3 | result:T; 4 | process(a: T, b: T) => T; 5 | } 6 | 7 | interface KeyPair { 8 | key: T; 9 | value: U; 10 | } 11 | 12 | let kv1: KeyPair = { key:1, value:"Steve" }; // OK 13 | let kv2: KeyPair = { key:1, value:12345 }; // OK 14 | 15 | interface KeyValueProcessor 16 | { 17 | (key: T, val: U): void; 18 | }; 19 | 20 | function processNumKeyPairs(key:number, value:number):void { 21 | console.log('processNumKeyPairs: key = ' + key + ', value = ' + value) 22 | } -------------------------------------------------------------------------------- /_fixtures/ts/grammar/Import.ts: -------------------------------------------------------------------------------- 1 | import { ZipCodeValidator } from "./ZipCodeValidator"; 2 | import * as validator from "./ZipCodeValidator"; 3 | import "./my-module.js"; 4 | import $ from "JQuery"; 5 | import zip = require("./ZipCodeValidator"); 6 | -------------------------------------------------------------------------------- /_fixtures/ts/grammar/Module.ts: -------------------------------------------------------------------------------- 1 | export let age : number = 20; 2 | export class Employee { 3 | empCode: number; 4 | empName: string; 5 | constructor(name: string, code: number) { 6 | this.empName = name; 7 | this.empCode = code; 8 | } 9 | displayEmployee() { 10 | console.log ("Employee Code: " + this.empCode + ", Employee Name: " + this.empName ); 11 | } 12 | } 13 | let companyName:string = "XYZ"; -------------------------------------------------------------------------------- /_fixtures/ts/grammar/Statement.ts: -------------------------------------------------------------------------------- 1 | let x: number = 10, y = 20; 2 | 3 | // If-else 4 | 5 | if (x > y) 6 | { 7 | console.log('x is greater than y.'); 8 | } 9 | else 10 | { 11 | console.log('x is less than or equal to y.'); //This will be executed 12 | } 13 | 14 | // Switch 15 | switch (x-y) { 16 | case 0: 17 | console.log("Result: 0"); 18 | break; 19 | case 5: 20 | console.log("Result: 5"); 21 | break; 22 | case 10: 23 | console.log("Result: 10"); 24 | break; 25 | } 26 | 27 | // For 28 | for (let i = 0; i < 3; i++) { 29 | console.log ("Block statement execution no." + i); 30 | } 31 | 32 | let str = "Hello World"; 33 | 34 | for (var char of str) { 35 | console.log(char); // prints chars: H e l l o W o r l d 36 | } 37 | 38 | let arr = [10, 20, 30, 40]; 39 | 40 | for (var index in arr) { 41 | console.log(index); // prints indexes: 0, 1, 2, 3 42 | 43 | console.log(arr[index]); // prints elements: 10, 20, 30, 40 44 | } 45 | 46 | // While 47 | let i: number = 2; 48 | do { 49 | console.log("Block statement execution no." + i ) 50 | i++; 51 | } while ( i < 4) 52 | 53 | while (i < 4) { 54 | console.log( "Block statement execution no." + i ) 55 | i++; 56 | } -------------------------------------------------------------------------------- /_fixtures/ts/grammar/Type.ts: -------------------------------------------------------------------------------- 1 | // TypeAnotation 2 | var age: number = 32; // number variable 3 | var name: string = "John";// string variable 4 | var isUpdated: boolean = true;// Boolean variable 5 | 6 | var employee : { 7 | id: number; 8 | name: string; 9 | }; 10 | 11 | employee = { 12 | id: 100, 13 | name : "John" 14 | } 15 | 16 | function display(id:number, name:string) 17 | { 18 | console.log("Id = " + id + ", Name = " + name); 19 | } 20 | 21 | 22 | // TypeInterface 23 | 24 | var arr = [0, 1, "test"]; 25 | arr.push("str") // OK 26 | arr.push(true); // Compiler Error: Argument of type 'true' is not assignable to parameter of type 'string | number' 27 | 28 | function sum(a: number, b: number ) 29 | { 30 | return a + b; 31 | } 32 | var total: number = sum(10,20); // OK 33 | var str: string = sum(10,20); // Compiler Error 34 | 35 | 36 | // TypeAssertion 37 | 38 | let code: any = 123; 39 | let employeeCode = code; 40 | console.log(typeof(employeeCode)); //Output: number 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /_fixtures/ts/grammar/Variable.ts: -------------------------------------------------------------------------------- 1 | let employeeName = "John"; 2 | // or 3 | let employeeName:string = "John"; 4 | 5 | var num1:number = 1; 6 | 7 | const playerCodes = { 8 | player1 : 9, 9 | player2 : 10, 10 | player3 : 13, 11 | player4 : 20 12 | }; 13 | playerCodes.player2 = 11; // OK 14 | 15 | playerCodes = { //Compiler Error: Cannot assign to playerCodes because it is a constant or read-only 16 | player1 : 50, // Modified value 17 | player2 : 10, 18 | player3 : 13, 19 | player4 : 20 20 | }; 21 | 22 | playerCodesArray = { //Compiler Error: Cannot assign to playerCodes because it is a constant or read-only 23 | player1 : 50, // Modified value 24 | player2 : playerCodes[Test], 25 | player3 : 13, 26 | player4 : 20 27 | }; -------------------------------------------------------------------------------- /_fixtures/ts/regressions/import_comma_issue.ts: -------------------------------------------------------------------------------- 1 | import bluebird from "bluebird"; 2 | import mongoose from "mongoose"; 3 | import { MONGODB_URI, SESSION_SECRET } from "./util/secrets"; 4 | 5 | const mongoUrl = MONGODB_URI; 6 | mongoose.Promise = bluebird; 7 | 8 | mongoose.connect(mongoUrl, { useNewUrlParser: true, useCreateIndex: true, useUnifiedTopology: true } ).then( 9 | () => { /** ready to use. The `mongoose.connect()` promise resolves to undefined. */ }, 10 | ).catch(err => { 11 | console.log("MongoDB connection error. Please make sure MongoDB is running. " + err); 12 | // process.exit(); 13 | }); 14 | -------------------------------------------------------------------------------- /_fixtures/ts/ts-node-starter/.gitignore: -------------------------------------------------------------------------------- 1 | package-lock.json 2 | node_modules/ 3 | -------------------------------------------------------------------------------- /_fixtures/ts/ts-node-starter/src/controllers/api.ts: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | import graph from "fbgraph"; 4 | import { Response, Request, NextFunction } from "express"; 5 | import { UserDocument } from "../models/User"; 6 | 7 | 8 | /** 9 | * GET /api 10 | * List of API examples. 11 | */ 12 | export const getApi = (req: Request, res: Response) => { 13 | res.render("api/index", { 14 | title: "API Examples" 15 | }); 16 | }; 17 | 18 | /** 19 | * GET /api/facebook 20 | * Facebook API example. 21 | */ 22 | export const getFacebook = (req: Request, res: Response, next: NextFunction) => { 23 | const user = req.user as UserDocument; 24 | const token = user.tokens.find((token: any) => token.kind === "facebook"); 25 | graph.setAccessToken(token.accessToken); 26 | graph.get(`${user.facebook}?fields=id,name,email,first_name,last_name,gender,link,locale,timezone`, (err: Error, results: graph.FacebookUser) => { 27 | if (err) { return next(err); } 28 | res.render("api/facebook", { 29 | title: "Facebook API", 30 | profile: results 31 | }); 32 | }); 33 | }; 34 | -------------------------------------------------------------------------------- /_fixtures/ts/ts-node-starter/src/controllers/home.ts: -------------------------------------------------------------------------------- 1 | import { Request, Response } from "express"; 2 | 3 | /** 4 | * GET / 5 | * Home page. 6 | */ 7 | export const index = (req: Request, res: Response) => { 8 | res.render("home", { 9 | title: "Home" 10 | }); 11 | }; 12 | -------------------------------------------------------------------------------- /_fixtures/ts/ts-node-starter/src/server.ts: -------------------------------------------------------------------------------- 1 | import errorHandler from "errorhandler"; 2 | 3 | import app from "./app"; 4 | 5 | /** 6 | * Error Handler. Provides full stack - remove for production 7 | */ 8 | app.use(errorHandler()); 9 | 10 | /** 11 | * Start Express server. 12 | */ 13 | const server = app.listen(app.get("port"), () => { 14 | console.log( 15 | " App is running at http://localhost:%d in %s mode", 16 | app.get("port"), 17 | app.get("env") 18 | ); 19 | console.log(" Press CTRL-C to stop\n"); 20 | }); 21 | 22 | export default server; 23 | -------------------------------------------------------------------------------- /_fixtures/ts/ts-node-starter/src/types/express-flash.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | 3 | /** 4 | * This type definition augments existing definition 5 | * from @types/express-flash 6 | */ 7 | declare namespace Express { 8 | export interface Request { 9 | flash(event: string, message: any): any; 10 | } 11 | } 12 | 13 | interface Flash { 14 | flash(type: string, message: any): void; 15 | } 16 | 17 | declare module "express-flash"; 18 | 19 | -------------------------------------------------------------------------------- /_fixtures/ts/ts-node-starter/src/util/logger.ts: -------------------------------------------------------------------------------- 1 | import winston from "winston"; 2 | 3 | const options: winston.LoggerOptions = { 4 | transports: [ 5 | new winston.transports.Console({ 6 | level: process.env.NODE_ENV === "production" ? "error" : "debug" 7 | }), 8 | new winston.transports.File({ filename: "debug.log", level: "debug" }) 9 | ] 10 | }; 11 | 12 | const logger = winston.createLogger(options); 13 | 14 | if (process.env.NODE_ENV !== "production") { 15 | logger.debug("Logging initialized at debug level"); 16 | } 17 | 18 | export default logger; 19 | -------------------------------------------------------------------------------- /_fixtures/ts/ts-node-starter/src/util/secrets.ts: -------------------------------------------------------------------------------- 1 | import logger from "./logger"; 2 | import dotenv from "dotenv"; 3 | import fs from "fs"; 4 | 5 | if (fs.existsSync(".env")) { 6 | logger.debug("Using .env file to supply config environment variables"); 7 | dotenv.config({ path: ".env" }); 8 | } else { 9 | logger.debug("Using .env.example file to supply config environment variables"); 10 | dotenv.config({ path: ".env.example" }); // you can delete this after you create your own .env file! 11 | } 12 | export const ENVIRONMENT = process.env.NODE_ENV; 13 | const prod = ENVIRONMENT === "production"; // Anything else is treated as 'dev' 14 | 15 | export const SESSION_SECRET = process.env["SESSION_SECRET"]; 16 | export const MONGODB_URI = prod ? process.env["MONGODB_URI"] : process.env["MONGODB_URI_LOCAL"]; 17 | 18 | if (!SESSION_SECRET) { 19 | logger.error("No client secret. Set SESSION_SECRET environment variable."); 20 | process.exit(1); 21 | } 22 | 23 | if (!MONGODB_URI) { 24 | if (prod) { 25 | logger.error("No mongo connection string. Set MONGODB_URI environment variable."); 26 | } else { 27 | logger.error("No mongo connection string. Set MONGODB_URI_LOCAL environment variable."); 28 | } 29 | process.exit(1); 30 | } 31 | -------------------------------------------------------------------------------- /_fixtures/visual/visual_demo.dot: -------------------------------------------------------------------------------- 1 | digraph G { 2 | subgraph cluster1 { 3 | label = "com" 4 | 5 | subgraph cluster2 { 6 | label = "phodal" 7 | node19 [ label="Ledge", shape=box ]; 8 | } 9 | subgraph cluster3 { 10 | label = "hug" 11 | node20 [ label="Spring", shape=box ]; 12 | } 13 | } 14 | 15 | node19 -> node20 16 | } -------------------------------------------------------------------------------- /analysis/dep/app/root.go: -------------------------------------------------------------------------------- 1 | package app 2 | 3 | import ( 4 | "github.com/spf13/cobra" 5 | "io" 6 | ) 7 | 8 | var ( 9 | output io.Writer 10 | rootCmd = &cobra.Command{ 11 | Use: "coa", 12 | Short: "A generator for Cobra based Applications", 13 | Long: `coa`, 14 | } 15 | ) 16 | 17 | func NewRootCmd(out io.Writer) *cobra.Command { 18 | output = out 19 | rootCmd.SetOut(out) 20 | return rootCmd 21 | } 22 | -------------------------------------------------------------------------------- /analysis/dep/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "github.com/modernizing/coca/analysis/golang/app" 5 | "os" 6 | ) 7 | 8 | func main() { 9 | output := os.Stdout 10 | rootCmd := app.NewRootCmd(output) 11 | _ = rootCmd.Execute() 12 | } 13 | -------------------------------------------------------------------------------- /analysis/golang/app/root.go: -------------------------------------------------------------------------------- 1 | package app 2 | 3 | import ( 4 | "github.com/spf13/cobra" 5 | "io" 6 | ) 7 | 8 | var ( 9 | output io.Writer 10 | rootCmd = &cobra.Command{ 11 | Use: "coa", 12 | Short: "A generator for Cobra based Applications", 13 | Long: `coa`, 14 | } 15 | ) 16 | 17 | func NewRootCmd(out io.Writer) *cobra.Command { 18 | output = out 19 | rootCmd.SetOut(out) 20 | return rootCmd 21 | } 22 | -------------------------------------------------------------------------------- /analysis/golang/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "github.com/modernizing/coca/analysis/golang/app" 5 | "os" 6 | ) 7 | 8 | func main() { 9 | output := os.Stdout 10 | rootCmd := app.NewRootCmd(output) 11 | _ = rootCmd.Execute() 12 | } 13 | -------------------------------------------------------------------------------- /analysis/java/app/root.go: -------------------------------------------------------------------------------- 1 | package app 2 | 3 | import ( 4 | "github.com/spf13/cobra" 5 | "io" 6 | ) 7 | 8 | var ( 9 | output io.Writer 10 | rootCmd = &cobra.Command{ 11 | Use: "coa", 12 | Short: "A generator for Cobra based Applications", 13 | Long: `coa`, 14 | } 15 | ) 16 | 17 | func NewRootCmd(out io.Writer) *cobra.Command { 18 | output = out 19 | rootCmd.SetOut(out) 20 | return rootCmd 21 | } 22 | -------------------------------------------------------------------------------- /analysis/java/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "github.com/modernizing/coca/analysis/java/app" 5 | "os" 6 | ) 7 | 8 | func main() { 9 | output := os.Stdout 10 | rootCmd := app.NewRootCmd(output) 11 | _ = rootCmd.Execute() 12 | } 13 | -------------------------------------------------------------------------------- /analysis/python/app/root.go: -------------------------------------------------------------------------------- 1 | package app 2 | 3 | import ( 4 | "github.com/spf13/cobra" 5 | "io" 6 | ) 7 | 8 | var ( 9 | output io.Writer 10 | rootCmd = &cobra.Command{ 11 | Use: "coa", 12 | Short: "A generator for Cobra based Applications", 13 | Long: `coa`, 14 | } 15 | ) 16 | 17 | func NewRootCmd(out io.Writer) *cobra.Command { 18 | output = out 19 | rootCmd.SetOut(out) 20 | return rootCmd 21 | } 22 | -------------------------------------------------------------------------------- /analysis/python/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "github.com/modernizing/coca/analysis/python/app" 5 | "os" 6 | ) 7 | 8 | func main() { 9 | output := os.Stdout 10 | rootCmd := app.NewRootCmd(output) 11 | _ = rootCmd.Execute() 12 | } 13 | -------------------------------------------------------------------------------- /cmd/analysis_test.go: -------------------------------------------------------------------------------- 1 | package cmd 2 | 3 | import ( 4 | "github.com/modernizing/coca/cocatest/testcase" 5 | "testing" 6 | ) 7 | 8 | func Test_Analysis_Java(t *testing.T) { 9 | path := "config" 10 | 11 | analysis := []testcase.CmdTestCase{{ 12 | Name: "analysis", 13 | Cmd: "analysis -p " + path, 14 | Golden: "testdata/analysis_java.txt", 15 | }} 16 | RunTestCmd(t, analysis) 17 | } 18 | -------------------------------------------------------------------------------- /cmd/api_test.go: -------------------------------------------------------------------------------- 1 | package cmd 2 | 3 | import ( 4 | "github.com/modernizing/coca/cocatest/testcase" 5 | "testing" 6 | ) 7 | 8 | func TestApi(t *testing.T) { 9 | path := "../_fixtures/call" 10 | 11 | analysis := []testcase.CmdTestCase{{ 12 | Name: "analysis", 13 | Cmd: "analysis -p " + path, 14 | Golden: "", 15 | }} 16 | RunTestCmd(t, analysis) 17 | 18 | tests := []testcase.CmdTestCase{{ 19 | Name: "api", 20 | Cmd: "api -c -f -p " + path, 21 | Golden: "testdata/api.txt", 22 | }} 23 | RunTestCmd(t, tests) 24 | } 25 | 26 | func Test_ApiWithSortRemove(t *testing.T) { 27 | path := "../_fixtures/call" 28 | 29 | analysis := []testcase.CmdTestCase{{ 30 | Name: "analysis", 31 | Cmd: "analysis -p " + path, 32 | Golden: "", 33 | }} 34 | RunTestCmd(t, analysis) 35 | 36 | tests := []testcase.CmdTestCase{{ 37 | Name: "api", 38 | Cmd: "api -c -s -r com.phodal.pholedge.book. -p" + path, 39 | Golden: "testdata/api_sort_remove.txt", 40 | }} 41 | RunTestCmd(t, tests) 42 | } 43 | -------------------------------------------------------------------------------- /cmd/arch_test.go: -------------------------------------------------------------------------------- 1 | package cmd 2 | 3 | import ( 4 | "github.com/modernizing/coca/cocatest/testcase" 5 | "testing" 6 | ) 7 | 8 | func TestArch(t *testing.T) { 9 | abs := "../_fixtures/arch" 10 | 11 | analysis := []testcase.CmdTestCase{{ 12 | Name: "analysis", 13 | Cmd: "analysis -p " + abs, 14 | Golden: "", 15 | }} 16 | RunTestCmd(t, analysis) 17 | 18 | tests := []testcase.CmdTestCase{{ 19 | Name: "arch", 20 | Cmd: "arch -P ", 21 | Golden: "", 22 | }} 23 | RunTestCmd(t, tests) 24 | 25 | header := []testcase.CmdTestCase{{ 26 | Name: "arch", 27 | Cmd: "arch -H -x \"com.phodal\"", 28 | Golden: "", 29 | }} 30 | RunTestCmd(t, header) 31 | } -------------------------------------------------------------------------------- /cmd/bs_test.go: -------------------------------------------------------------------------------- 1 | package cmd 2 | 3 | import ( 4 | "github.com/modernizing/coca/cocatest/testcase" 5 | "testing" 6 | ) 7 | 8 | func TestBadSmell(t *testing.T) { 9 | abs := "../_fixtures/bs" 10 | 11 | tests := []testcase.CmdTestCase{{ 12 | Name: "bs", 13 | Cmd: "bs -s type -p " + abs, 14 | Golden: "", 15 | }} 16 | RunTestCmd(t, tests) 17 | } 18 | -------------------------------------------------------------------------------- /cmd/call_test.go: -------------------------------------------------------------------------------- 1 | package cmd 2 | 3 | import ( 4 | "github.com/modernizing/coca/cocatest/testcase" 5 | "testing" 6 | ) 7 | 8 | func TestCall(t *testing.T) { 9 | abs := "../_fixtures/arch" 10 | 11 | analysis := []testcase.CmdTestCase{{ 12 | Name: "analysis", 13 | Cmd: "analysis -p " + abs, 14 | Golden: "", 15 | }} 16 | RunTestCmd(t, analysis) 17 | 18 | tests := []testcase.CmdTestCase{{ 19 | Name: "call", 20 | Cmd: "call -r com", 21 | Golden: "", 22 | }} 23 | RunTestCmd(t, tests) 24 | } 25 | -------------------------------------------------------------------------------- /cmd/cmd_util/coca_output.go: -------------------------------------------------------------------------------- 1 | package cmd_util 2 | 3 | import ( 4 | "github.com/olekukonko/tablewriter" 5 | "io" 6 | "strings" 7 | ) 8 | 9 | func NewOutput(output io.Writer) *tablewriter.Table { 10 | table := tablewriter.NewWriter(output) 11 | table.SetBorders(tablewriter.Border{Left: true, Top: false, Right: true, Bottom: false}) 12 | table.SetCenterSeparator("|") 13 | table.SetColWidth(80) 14 | return table 15 | } 16 | 17 | func NewCsv() (*tablewriter.Table, *strings.Builder) { 18 | tableString := &strings.Builder{} 19 | table := tablewriter.NewWriter(tableString) 20 | table.SetBorders(tablewriter.Border{Left: false, Top: false, Right: false, Bottom: false}) 21 | table.SetCenterSeparator("") 22 | table.SetRowSeparator("") 23 | table.SetColumnSeparator(",") 24 | table.SetColWidth(80) 25 | return table, tableString 26 | } 27 | -------------------------------------------------------------------------------- /cmd/cmd_util/deps_loader.go: -------------------------------------------------------------------------------- 1 | package cmd_util 2 | 3 | import ( 4 | "encoding/json" 5 | "github.com/modernizing/coca/pkg/domain/core_domain" 6 | ) 7 | 8 | func GetDepsFromJson(depPath string) []core_domain.CodeDataStruct { 9 | var parsedDeps []core_domain.CodeDataStruct 10 | file := ReadFile(depPath) 11 | _ = json.Unmarshal(file, &parsedDeps) 12 | 13 | return parsedDeps 14 | } 15 | 16 | -------------------------------------------------------------------------------- /cmd/cmd_util/file_rw_helper.go: -------------------------------------------------------------------------------- 1 | package cmd_util 2 | 3 | import ( 4 | "fmt" 5 | "github.com/modernizing/coca/cmd/config" 6 | "io/ioutil" 7 | "os" 8 | "path/filepath" 9 | ) 10 | 11 | var reporterPath = config.CocaConfig.ReporterPath 12 | 13 | func WriteToCocaFile(fileName string, payload string) { 14 | if _, err := os.Stat(reporterPath); os.IsNotExist(err) { 15 | mkdirErr := os.Mkdir(reporterPath, os.ModePerm) 16 | if mkdirErr != nil { 17 | fmt.Println(mkdirErr) 18 | } 19 | } 20 | _ = ioutil.WriteFile(filepath.FromSlash(reporterPath+"/"+fileName), []byte(payload), os.ModePerm) 21 | } 22 | 23 | func ReadCocaFile(fileName string) []byte { 24 | return ReadFile(filepath.FromSlash(reporterPath + "/" + fileName)) 25 | } 26 | 27 | func ReadFile(fileName string) []byte { 28 | contents, err := ioutil.ReadFile(fileName) 29 | if err != nil { 30 | _ = fmt.Errorf("Failed read file: %s ", err) 31 | return nil 32 | } 33 | return contents 34 | } 35 | -------------------------------------------------------------------------------- /cmd/cmd_util/osexec.go: -------------------------------------------------------------------------------- 1 | package cmd_util 2 | 3 | import ( 4 | "fmt" 5 | "github.com/modernizing/coca/cmd/config" 6 | "os/exec" 7 | ) 8 | 9 | func ConvertToSvg(name string) { 10 | reporter_path := config.CocaConfig.ReporterPath 11 | cmd := exec.Command("dot", "-Tsvg", reporter_path+"/"+name+".dot", "-o", reporter_path+"/"+name+".svg") 12 | _, err := cmd.CombinedOutput() 13 | if err != nil { 14 | fmt.Println("cmd.Run() failed with:", err) 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /cmd/coca_test.go: -------------------------------------------------------------------------------- 1 | package cmd 2 | 3 | import ( 4 | "github.com/modernizing/coca/cocatest" 5 | "github.com/modernizing/coca/cocatest/testcase" 6 | "testing" 7 | ) 8 | 9 | func RunTestCmd(t *testing.T, tests []testcase.CmdTestCase) { 10 | cocatest.RunTestCaseWithCmd(t, tests, NewRootCmd) 11 | } 12 | 13 | -------------------------------------------------------------------------------- /cmd/concept_test.go: -------------------------------------------------------------------------------- 1 | package cmd 2 | 3 | import ( 4 | "github.com/modernizing/coca/cocatest/testcase" 5 | "testing" 6 | ) 7 | 8 | func TestConcept(t *testing.T) { 9 | analysis := []testcase.CmdTestCase{{ 10 | Name: "analysis", 11 | Cmd: "analysis -p ../_fixtures/grammar/java/examples/api", 12 | Golden: "", 13 | }} 14 | RunTestCmd(t, analysis) 15 | 16 | tests := []testcase.CmdTestCase{{ 17 | Name: "concept", 18 | Cmd: "concept", 19 | Golden: "testdata/concept.txt", 20 | }} 21 | RunTestCmd(t, tests) 22 | } -------------------------------------------------------------------------------- /cmd/config/cmd_config.go: -------------------------------------------------------------------------------- 1 | package config 2 | 3 | type TypeCocaConfig struct { 4 | ReporterPath string 5 | ClocDir string 6 | } 7 | 8 | var CocaConfig = &TypeCocaConfig{ 9 | ReporterPath: "coca_reporter", 10 | ClocDir: "/cloc", 11 | } 12 | 13 | const VERSION = "2.4.1" 14 | -------------------------------------------------------------------------------- /cmd/count_test.go: -------------------------------------------------------------------------------- 1 | package cmd 2 | 3 | import ( 4 | "github.com/modernizing/coca/cocatest/testcase" 5 | "testing" 6 | ) 7 | 8 | func TestCount(t *testing.T) { 9 | abs := "../_fixtures/grammar/java/examples/rename" 10 | 11 | analysis := []testcase.CmdTestCase{{ 12 | Name: "analysis", 13 | Cmd: "analysis -p " + abs, 14 | Golden: "", 15 | }} 16 | RunTestCmd(t, analysis) 17 | 18 | tests := []testcase.CmdTestCase{{ 19 | Name: "count", 20 | Cmd: "count -t 1", 21 | Golden: "testdata/count.txt", 22 | }} 23 | RunTestCmd(t, tests) 24 | } 25 | -------------------------------------------------------------------------------- /cmd/evaluate_test.go: -------------------------------------------------------------------------------- 1 | package cmd 2 | 3 | import ( 4 | "github.com/modernizing/coca/cocatest/testcase" 5 | "testing" 6 | ) 7 | 8 | func TestEvaluate(t *testing.T) { 9 | analysis := []testcase.CmdTestCase{{ 10 | Name: "analysis", 11 | Cmd: "analysis -p ../_fixtures/grammar/java/arch", 12 | Golden: "", 13 | }} 14 | RunTestCmd(t, analysis) 15 | 16 | tests := []testcase.CmdTestCase{{ 17 | Name: "evaluate", 18 | Cmd: "evaluate", 19 | Golden: "testdata/evaluate.txt", 20 | }} 21 | RunTestCmd(t, tests) 22 | } 23 | -------------------------------------------------------------------------------- /cmd/git_test.go: -------------------------------------------------------------------------------- 1 | package cmd 2 | 3 | import ( 4 | "github.com/modernizing/coca/cocatest/testcase" 5 | "testing" 6 | ) 7 | 8 | // Todo: fake it 9 | func TestGit(t *testing.T) { 10 | tests := []testcase.CmdTestCase{{ 11 | Name: "git", 12 | Cmd: "git -a -f -t -b -o -r com -s 10 -m", 13 | Golden: "", 14 | }} 15 | RunTestCmd(t, tests) 16 | } 17 | -------------------------------------------------------------------------------- /cmd/rcall_test.go: -------------------------------------------------------------------------------- 1 | package cmd 2 | 3 | import ( 4 | "github.com/modernizing/coca/cocatest/testcase" 5 | "testing" 6 | ) 7 | 8 | func TestRCall(t *testing.T) { 9 | analysis := []testcase.CmdTestCase{{ 10 | Name: "analysis", 11 | Cmd: "analysis -p ../_fixtures/call", 12 | Golden: "", 13 | }} 14 | RunTestCmd(t, analysis) 15 | 16 | tests := []testcase.CmdTestCase{{ 17 | Name: "rcall", 18 | Cmd: "rcall -r com -c com", 19 | Golden: "testdata/rcall_normal.txt", 20 | }} 21 | RunTestCmd(t, tests) 22 | } 23 | -------------------------------------------------------------------------------- /cmd/refactor_test.go: -------------------------------------------------------------------------------- 1 | package cmd 2 | 3 | import ( 4 | "github.com/modernizing/coca/cocatest/testcase" 5 | "testing" 6 | ) 7 | 8 | func TestRefactorMove(t *testing.T) { 9 | tests := []testcase.CmdTestCase{{ 10 | Name: "refactor", 11 | Cmd: "refactor -p . -m .", 12 | Golden: "", 13 | }} 14 | RunTestCmd(t, tests) 15 | } 16 | 17 | func TestRefactorRename(t *testing.T) { 18 | tests := []testcase.CmdTestCase{{ 19 | Name: "refactor", 20 | Cmd: "refactor -p . -R . -m .", 21 | Golden: "", 22 | }} 23 | RunTestCmd(t, tests) 24 | } 25 | -------------------------------------------------------------------------------- /cmd/root.go: -------------------------------------------------------------------------------- 1 | package cmd 2 | 3 | import ( 4 | "github.com/spf13/cobra" 5 | "io" 6 | ) 7 | 8 | var ( 9 | output io.Writer 10 | rootCmd = &cobra.Command{ 11 | Use: "coca", 12 | Short: "A generator for Cobra based Applications", 13 | Long: `coca`, 14 | } 15 | ) 16 | 17 | func NewRootCmd(out io.Writer) *cobra.Command { 18 | output = out 19 | rootCmd.SetOut(out) 20 | return rootCmd 21 | } 22 | -------------------------------------------------------------------------------- /cmd/suggest_test.go: -------------------------------------------------------------------------------- 1 | package cmd 2 | 3 | import ( 4 | "github.com/modernizing/coca/cocatest/testcase" 5 | "testing" 6 | ) 7 | 8 | func TestSuggest(t *testing.T) { 9 | analysis := []testcase.CmdTestCase{{ 10 | Name: "analysis", 11 | Cmd: "analysis -p ../_fixtures/suggest", 12 | Golden: "", 13 | }} 14 | RunTestCmd(t, analysis) 15 | 16 | tests := []testcase.CmdTestCase{{ 17 | Name: "suggest", 18 | Cmd: "suggest", 19 | Golden: "testdata/suggest_normal.txt", 20 | }} 21 | RunTestCmd(t, tests) 22 | } 23 | -------------------------------------------------------------------------------- /cmd/tbs_test.go: -------------------------------------------------------------------------------- 1 | package cmd 2 | 3 | import ( 4 | "github.com/modernizing/coca/cocatest/testcase" 5 | "testing" 6 | ) 7 | 8 | func TestTbs(t *testing.T) { 9 | tests := []testcase.CmdTestCase{{ 10 | Name: "tbs", 11 | Cmd: "tbs -p ../_fixtures/tbs/usecases -s ", 12 | Golden: "testdata/tbs_normal.txt", 13 | }} 14 | RunTestCmd(t, tests) 15 | } 16 | -------------------------------------------------------------------------------- /cmd/testdata/analysis_java.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phodal/coca/ba6db6c24a138a6799d6784b7b884349d73c98a4/cmd/testdata/analysis_java.txt -------------------------------------------------------------------------------- /cmd/testdata/api.txt: -------------------------------------------------------------------------------- 1 | | SIZE | METHOD | URI | CALLER | 2 | |------|--------|-------------|-----------------------------------------------------| 3 | | 2 | POST | /books | com.phodal.pholedge.book.BookController.createBook | 4 | | 2 | PUT | /books/{id} | com.phodal.pholedge.book.BookController.updateBook | 5 | | 2 | GET | /books/ | com.phodal.pholedge.book.BookController.getBookList | 6 | | 2 | GET | /books/{id} | com.phodal.pholedge.book.BookController.getBookById | 7 | -------------------------------------------------------------------------------- /cmd/testdata/api_sort_remove.txt: -------------------------------------------------------------------------------- 1 | | SIZE | METHOD | URI | CALLER | 2 | |------|--------|-------------|----------------------------| 3 | | 2 | POST | /books | BookController.createBook | 4 | | 2 | PUT | /books/{id} | BookController.updateBook | 5 | | 2 | GET | /books/ | BookController.getBookList | 6 | | 2 | GET | /books/{id} | BookController.getBookById | 7 | -------------------------------------------------------------------------------- /cmd/testdata/cloc_directory.txt: -------------------------------------------------------------------------------- 1 | package,summary,Java,Kotlin 2 | pkg,20,17,3 3 | -------------------------------------------------------------------------------- /cmd/testdata/cloc_ignore.txt: -------------------------------------------------------------------------------- 1 | package,summary,Java 2 | -------------------------------------------------------------------------------- /cmd/testdata/concept.txt: -------------------------------------------------------------------------------- 1 | | WORDS | COUNTS | 2 | |----------------|--------| 3 | | book | 11 | 4 | | books | 1 | 5 | | controller | 1 | 6 | | list | 3 | 7 | | lists | 1 | 8 | | repository | 1 | 9 | | representation | 1 | 10 | | service | 1 | 11 | -------------------------------------------------------------------------------- /cmd/testdata/count.txt: -------------------------------------------------------------------------------- 1 | | REFS COUNT | METHOD | 2 | |------------|------------------------------------------------------------| 3 | | 1 | study.huhao.demo.infrastructure.persistence.blog.BlogPO.of | 4 | -------------------------------------------------------------------------------- /cmd/testdata/deps_gradle.txt: -------------------------------------------------------------------------------- 1 | unused 2 | | GROUPID | ARTIFACTID | SCOPE | 3 | |---------------------------|-------------------------------------------|--------------------| 4 | | org.flywaydb | flyway-core | implementation | 5 | | org.springframework.cloud | spring-cloud-starter-zipkin | implementation | 6 | | org.springframework.cloud | spring-cloud-starter-zookeeper-config | implementation | 7 | | io.projectreactor | reactor-test | testImplementation | 8 | | org.springframework.cloud | spring-cloud-starter-contract-stub-runner | testImplementation | 9 | | org.springframework.cloud | spring-cloud-starter-contract-verifier | testImplementation | 10 | -------------------------------------------------------------------------------- /cmd/testdata/deps_maven.txt: -------------------------------------------------------------------------------- 1 | unused 2 | | GROUPID | ARTIFACTID | SCOPE | 3 | |---------------------------|----------------------------------------|---------| 4 | | org.flywaydb | flyway-core | | 5 | | mysql | mysql-connector-java | runtime | 6 | | org.springframework.cloud | spring-cloud-starter-contract-verifier | test | 7 | -------------------------------------------------------------------------------- /cmd/testdata/evaluate.txt: -------------------------------------------------------------------------------- 1 | | TYPE | TYPE COUNT | LEVEL | LEVEL TOTAL | VALUE = COUNT / TOTAL | 2 | |--------------------------------|------------|-----------------------|-------------|-----------------------| 3 | | Nullable / Return Null | 0 | Method | 6 | 0.00% | 4 | | Utils | 0 | Class | 14 | 0.00% | 5 | | Static Method | 1 | Method | 6 | 0.00% | 6 | | Average Method Num. | 6 | Method/Class | 14 | 0.428571 | 7 | | Method Num. Std Dev / 标准差 | 6 | Class | - | 0.646206 | 8 | | Average Method Length | 0 | Without Getter/Setter | 0 | NaN | 9 | | Method Length Std Dev / 标准差 | 0 | Method | - | NaN | 10 | -------------------------------------------------------------------------------- /cmd/testdata/rcall_normal.txt: -------------------------------------------------------------------------------- 1 | start rcall class: com 2 | -------------------------------------------------------------------------------- /cmd/testdata/suggest_normal.txt: -------------------------------------------------------------------------------- 1 | | CLASS | PATTERN | REASON | 2 | |------------|------------------|----------------------------------------------------------------| 3 | | BeeBuilder | factory, builder | too many constructor, too many parameters | 4 | | Insect | factory | too many constructor | 5 | | Bee | factory, builder | complex constructor, too many constructor, too many parameters | 6 | -------------------------------------------------------------------------------- /cmd/testdata/todo_filter.txt: -------------------------------------------------------------------------------- 1 | Todos Count 1 2 | | FILENAME | MESSAGES | ASSIGNEE | LINE | 3 | |-------------------------------|-------------------------------------|----------|------| 4 | | ../_fixtures/todo/todo.phodal | add todo for other text like phodal | | 1 | 5 | -------------------------------------------------------------------------------- /cmd/testdata/todo_normal.txt: -------------------------------------------------------------------------------- 1 | Todos Count 4 2 | | FILENAME | MESSAGES | ASSIGNEE | LINE | 3 | |-----------------------------|--------------------------|----------|------| 4 | | ../_fixtures/todo/Todo.go | add todo test for golang | | 3 | 5 | | ../_fixtures/todo/Todo.java | update | | 6 | 6 | | ../_fixtures/todo/Todo.java | add more content | phodal | 13 | 7 | | ../_fixtures/todo/todo.py | add todo for python | | 1 | 8 | -------------------------------------------------------------------------------- /cmd/testdata/top_file.txt: -------------------------------------------------------------------------------- 1 | Language: Java 2 | | LENGTH | COMPLEXITY | LOCATION | 3 | |--------|------------|----------------------------| 4 | | 40 | 0 | actory/Bee.java | 5 | | 19 | 0 | builder/Bee.java | 6 | | 13 | 0 | polymorphism/Overload.java | 7 | | 4 | 0 | atic/StaticMain.java | 8 | -------------------------------------------------------------------------------- /cmd/todo_test.go: -------------------------------------------------------------------------------- 1 | package cmd 2 | 3 | import ( 4 | "github.com/modernizing/coca/cocatest/testcase" 5 | "testing" 6 | ) 7 | 8 | func Test_ShouldOutputCount(t *testing.T) { 9 | tests := []testcase.CmdTestCase{{ 10 | Name: "todo", 11 | Cmd: "todo -p ../_fixtures/todo", 12 | Golden: "testdata/todo_normal.txt", 13 | }} 14 | RunTestCmd(t, tests) 15 | } 16 | 17 | func Test_ShouldFilterTodo(t *testing.T) { 18 | tests := []testcase.CmdTestCase{{ 19 | Name: "todo", 20 | Cmd: "todo -p ../_fixtures/todo --ext=.phodal", 21 | Golden: "testdata/todo_filter.txt", 22 | }} 23 | RunTestCmd(t, tests) 24 | } 25 | 26 | //TODO: update func for CI which clone depth = 1 27 | func TestTodo(t *testing.T) { 28 | tests := []testcase.CmdTestCase{{ 29 | Name: "todo", 30 | Cmd: "todo -p ../_fixtures/todo -g", 31 | Golden: "", 32 | }} 33 | RunTestCmd(t, tests) 34 | } 35 | -------------------------------------------------------------------------------- /cmd/version.go: -------------------------------------------------------------------------------- 1 | package cmd 2 | 3 | import ( 4 | "fmt" 5 | "github.com/modernizing/coca/cmd/config" 6 | "github.com/spf13/cobra" 7 | ) 8 | 9 | func init() { 10 | versionCmd.SetOut(output) 11 | rootCmd.AddCommand(versionCmd) 12 | } 13 | 14 | var versionCmd = &cobra.Command{ 15 | Use: "version", 16 | Short: "version", 17 | Run: func(cmd *cobra.Command, args []string) { 18 | fmt.Fprintf(output, "Coca Version: "+config.VERSION+" -- HEAD") 19 | }, 20 | } -------------------------------------------------------------------------------- /cmd/version_test.go: -------------------------------------------------------------------------------- 1 | package cmd 2 | 3 | import ( 4 | "github.com/modernizing/coca/cocatest/testcase" 5 | "testing" 6 | ) 7 | 8 | func TestVersion(t *testing.T) { 9 | tests := []testcase.CmdTestCase{{ 10 | Name: "version", 11 | Cmd: "version", 12 | Golden: "", 13 | }} 14 | RunTestCmd(t, tests) 15 | } -------------------------------------------------------------------------------- /coca.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "github.com/modernizing/coca/cmd" 6 | "github.com/pkg/profile" 7 | "os" 8 | "time" 9 | ) 10 | 11 | func main() { 12 | t1 := time.Now() // get current time 13 | defer profile.Start().Stop() 14 | output := os.Stdout 15 | rootCmd := cmd.NewRootCmd(output) 16 | _ = rootCmd.Execute() 17 | elapsed := time.Since(t1) 18 | fmt.Println("App elapsed: ", elapsed) 19 | } 20 | -------------------------------------------------------------------------------- /cocatest/panic_assert.go: -------------------------------------------------------------------------------- 1 | package cocatest 2 | 3 | import "testing" 4 | 5 | func AssertPanic(t *testing.T, panicFunc func()) { 6 | defer func() { 7 | if r := recover(); r == nil { 8 | t.Errorf("The code did not panic") 9 | } 10 | }() 11 | panicFunc() 12 | } 13 | -------------------------------------------------------------------------------- /cocatest/testcase/testcase.go: -------------------------------------------------------------------------------- 1 | package testcase 2 | 3 | // CmdTestCase describes a test case that works with releases. 4 | type CmdTestCase struct { 5 | Name string 6 | Cmd string 7 | Golden string 8 | WantError bool 9 | } 10 | 11 | -------------------------------------------------------------------------------- /cocatest/testhelper/generate.go: -------------------------------------------------------------------------------- 1 | package testhelper 2 | 3 | import ( 4 | "github.com/modernizing/coca/pkg/application/analysis/javaapp" 5 | "github.com/modernizing/coca/pkg/domain/core_domain" 6 | "path/filepath" 7 | ) 8 | 9 | func BuildAnalysisDeps(codePath string) ([]core_domain.CodeDataStruct, map[string]core_domain.CodeDataStruct, []core_domain.CodeDataStruct) { 10 | codePath = filepath.FromSlash(codePath) 11 | 12 | identifierApp := javaapp.NewJavaIdentifierApp() 13 | identifiers := identifierApp.AnalysisPath(codePath) 14 | 15 | callApp := javaapp.NewJavaFullApp() 16 | callNodes := callApp.AnalysisPath(codePath, identifiers) 17 | 18 | identifiersMap := core_domain.BuildIdentifierMap(identifiers) 19 | return callNodes, identifiersMap, identifiers 20 | } 21 | 22 | -------------------------------------------------------------------------------- /cocatest/testhelper/git_reset.go: -------------------------------------------------------------------------------- 1 | package testhelper 2 | 3 | import ( 4 | "fmt" 5 | "os/exec" 6 | ) 7 | 8 | func ResetGitDir(codePath string) { 9 | cmd := exec.Command("git", "checkout", "--ignore-skip-worktree-bits", "--", codePath) 10 | 11 | out, err := cmd.CombinedOutput() 12 | if err != nil { 13 | fmt.Println(string(out)) 14 | fmt.Println("cmd.Run() failed with: ", err) 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /codecov.yml: -------------------------------------------------------------------------------- 1 | ignore: 2 | - "languages" 3 | - "bughunt" 4 | - "cocatest" 5 | - "analysis" -------------------------------------------------------------------------------- /docs/README.md: -------------------------------------------------------------------------------- 1 | # Doc 2 | 3 | ## TODO 4 | 5 | - optimization import. 6 | - rename field. 7 | - move method. 8 | 9 | 10 | ## Go Domain 11 | 12 | Go To JavaScript: https://github.com/gopherjs/gopherjs -------------------------------------------------------------------------------- /docs/adr/0001-api-scan-sql.md: -------------------------------------------------------------------------------- 1 | # 1. Api scan SQL 2 | 3 | Date: 2019-11-07 4 | 5 | ## Status 6 | 7 | 2019-11-07 proposed 8 | 9 | ## Context 10 | 11 | Context here... 12 | 13 | ## Decision 14 | 15 | Decision here... 16 | 17 | ## Consequences 18 | 19 | Consequences here... 20 | -------------------------------------------------------------------------------- /docs/adr/0002-spring-mvc-to-spring-boot-transform.md: -------------------------------------------------------------------------------- 1 | # 2. Spring MVC to Spring Boot transform 2 | 3 | Date: 2019-11-18 4 | 5 | ## Status 6 | 7 | 2019-11-18 proposed 8 | 9 | ## Context 10 | 11 | Context here... 12 | 13 | ## Decision 14 | 15 | Decision here... 16 | 17 | ## Consequences 18 | 19 | Consequences here... 20 | -------------------------------------------------------------------------------- /docs/adr/0003-api-identify.md: -------------------------------------------------------------------------------- 1 | # 3. API Identify 2 | 3 | Date: 2019-12-17 4 | 5 | ## Status 6 | 7 | 2019-12-17 done 8 | 9 | ## Context 10 | 11 | 1. 看 API 与 Controller 是否对应 12 | 2. method 里使用了 RequestMapping 可能会出错。 13 | 14 | ## Decision 15 | 16 | Decision here... 17 | 18 | ## Consequences 19 | 20 | Consequences here... 21 | -------------------------------------------------------------------------------- /docs/adr/0004-handidraw-graphviz.md: -------------------------------------------------------------------------------- 1 | # 4. handidraw graphviz 2 | 3 | Date: 2019-12-17 4 | 5 | ## Status 6 | 7 | 2019-12-17 proposed 8 | 9 | 2020-11-04 deprecated 10 | 11 | ## Context 12 | 13 | Examples: https://github.com/aivarsk/scruffy 14 | 15 | ## Decision 16 | 17 | Decision here... 18 | 19 | ## Consequences 20 | 21 | Consequences here... 22 | -------------------------------------------------------------------------------- /docs/adr/0005-evaluate-api.md: -------------------------------------------------------------------------------- 1 | # 5. Evaluate API 2 | 3 | Date: 2019-12-17 4 | 5 | ## Status 6 | 7 | 2019-12-17 proposed 8 | 2020-01-01 done 9 | 10 | ## Context 11 | 12 | 1. 解析 Gradle 和 Maven 的依赖,判断是 Spring 项目还是普通的 Maven 项目,并从中读取依赖相关的信息。 13 | 14 | 15 | 一个示例的 Maven 解析器:https://github.com/creekorful/mvnparser 16 | 17 | Gradle 可以用: https://github.com/groovy/groovy-core/blob/master/src/main/org/codehaus/groovy/antlr/groovy.g 18 | 19 | or Find in Code ? 20 | 21 | 22 | 2. NLP 分层 Utils 23 | 24 | Util 方法通过 NLP 聚合,再进行分层 25 | 26 | 通过聚类算法分析某个方法的相关功能。 27 | 28 | 3. 输入参数 + 返回类型 29 | 30 | 1. 如存在多个输入参数 date, time, eventName, blabla,关联 bad smell 中的 31 | 32 | ## Decision 33 | 34 | Decision here... 35 | 36 | ## Consequences 37 | 38 | Consequences here... 39 | -------------------------------------------------------------------------------- /docs/adr/0006-support-adapter-to-cli-framework.md: -------------------------------------------------------------------------------- 1 | # 6. support adapter to cli framework 2 | 3 | Date: 2019-12-21 4 | 5 | ## Status 6 | 7 | 2019-12-21 proposed 8 | 2020-01-01 done 9 | 10 | ## Context 11 | 12 | 整洁架构,所以可以参考: 13 | 14 | https://github.com/onsi/ginkgo/blob/4cb744166b80afeec15fd0b4446c640a7688cd51/ginkgo/main.go 15 | 16 | ## Decision 17 | 18 | Decision here... 19 | 20 | ## Consequences 21 | 22 | Consequences here... 23 | -------------------------------------------------------------------------------- /docs/adr/0008-testable-evaluate.md: -------------------------------------------------------------------------------- 1 | # 8. testable evaluate 2 | 3 | Date: 2019-12-25 4 | 5 | ## Status 6 | 7 | 2019-12-25 proposed 8 | 9 | ## Context 10 | 11 | Context here... 12 | 13 | - 平均方法长度 14 | static 方法数 15 | 16 | ## Decision 17 | 18 | Decision here... 19 | 20 | ## Consequences 21 | 22 | Consequences here... 23 | -------------------------------------------------------------------------------- /docs/adr/0009-git-tell-file-history.md: -------------------------------------------------------------------------------- 1 | # 9. git tell file history 2 | 3 | Date: 2019-12-25 4 | 5 | ## Status 6 | 7 | 2019-12-25 proposed 8 | 2020-01-01 done 9 | 10 | ## Context 11 | 12 | Refs: https://stackoverflow.com/questions/9935379/git-show-all-of-the-various-changes-to-a-single-line-in-a-specified-file-over-t 13 | 14 | Show Line History: 15 | 16 | ``` 17 | git log -L3,5:README.md 18 | ``` 19 | 20 | Show String History 21 | 22 | ``` 23 | git log -G "## Usage" README.md 24 | ``` 25 | 26 | More: 27 | 28 | ``` 29 | for c in $(git log -G "## Usage" --format=%H -- README.md); do 30 | git --no-pager grep -e "## Usage" $c -- README.md 31 | done 32 | ``` 33 | 34 | Blame: 35 | 36 | ``` 37 | git blame README.md 38 | ``` 39 | 40 | ## Decision 41 | 42 | Decision here... 43 | 44 | ## Consequences 45 | 46 | Consequences here... 47 | -------------------------------------------------------------------------------- /docs/adr/0010-pluginable.md: -------------------------------------------------------------------------------- 1 | # 10. pluginable 2 | 3 | Date: 2020-01-02 4 | 5 | ## Status 6 | 7 | 2020-01-02 proposed 8 | 9 | ## Context 10 | 11 | Some resources: 12 | 13 | 1. https://medium.com/nordcloud-engineering/how-to-build-pluggable-golang-application-and-benefit-from-aws-lambda-layers-154c8117df9b 14 | 2. https://medium.com/learning-the-go-programming-language/writing-modular-go-programs-with-plugins-ec46381ee1a9 15 | 16 | ## Decision 17 | 18 | Decision here... 19 | 20 | ## Consequences 21 | 22 | Consequences here... 23 | -------------------------------------------------------------------------------- /docs/adr/0011-module-treemap-visualization.md: -------------------------------------------------------------------------------- 1 | # 11. module treemap visualization 2 | 3 | Date: 2020-01-02 4 | 5 | ## Status 6 | 7 | 2020-01-02 proposed 8 | 9 | ## Context 10 | 11 | Context here... 12 | 13 | examples: https://www.npmjs.com/package/webpack-bundle-analyzer 14 | 15 | A Golang Examples: https://github.com/willpoint/treemap/blob/master/treemap.go 16 | 17 | ## Decision 18 | 19 | Decision here... 20 | 21 | ## Consequences 22 | 23 | Consequences here... 24 | -------------------------------------------------------------------------------- /docs/adr/0012-check-dependence-usage-for-module-seperate.md: -------------------------------------------------------------------------------- 1 | # 12. check dependence usage for module seperate 2 | 3 | Date: 2020-01-03 4 | 5 | ## Status 6 | 7 | 2020-01-03 proposed 8 | 9 | ## Context 10 | 11 | - Groovy 12 | - Antlr 插件化 13 | 14 | ## Decision 15 | 16 | Decision here... 17 | 18 | ## Consequences 19 | 20 | Consequences here... 21 | -------------------------------------------------------------------------------- /docs/adr/0013-performance-issue-for-antlar.md: -------------------------------------------------------------------------------- 1 | # 13. performance issue for antlr 2 | 3 | Date: 2020-01-12 4 | 5 | ## Status 6 | 7 | 2020-01-12 proposed 8 | 9 | 2020-11-04 deprecated 10 | 11 | ## Context 12 | 13 | Context here... 14 | 15 | ## Decision 16 | 17 | Decision here... 18 | 19 | ## Consequences 20 | 21 | Consequences here... 22 | -------------------------------------------------------------------------------- /docs/adr/0014-improve-cloc-summary.md: -------------------------------------------------------------------------------- 1 | # 14. improve cloc summary 2 | 3 | Date: 2020-11-04 4 | 5 | ## Status 6 | 7 | 2020-11-04 proposed 8 | 9 | 2020-11-04 done 10 | 11 | ## Context 12 | 13 | Context here... 14 | 15 | ## Decision 16 | 17 | - exclude `coca_reporter` 18 | 19 | ## Consequences 20 | 21 | Consequences here... 22 | -------------------------------------------------------------------------------- /docs/adr/0015-light-weight-coca.md: -------------------------------------------------------------------------------- 1 | # 15. light weight coca 2 | 3 | Date: 2020-11-04 4 | 5 | ## Status 6 | 7 | 2020-11-04 proposed 8 | 9 | ## Context 10 | 11 | For a lots situation, we don't need to visit code, just by git & cloc, we can build most information. In this case, we 12 | need a light version with Coca. 13 | 14 | For this version, it can support those features: 15 | 16 | 1. analysis code from top to bottom with `cloc`. 17 | 2. analysis todo with antlr4 18 | 3. analysis git history with `git` 19 | 4. analysis `imports` for major languages: 20 | - c++ 21 | - golang 22 | - java 23 | - kotlin 24 | - javascript 25 | 26 | if we need more useful features, we can also do: 27 | 28 | 1. analysis dependencies 29 | 30 | ## Decision 31 | 32 | Decision here... 33 | 34 | ## Consequences 35 | 36 | Consequences here... 37 | -------------------------------------------------------------------------------- /docs/adr/0016-git-branch-analysis.md: -------------------------------------------------------------------------------- 1 | # 16. git branch analysis 2 | 3 | Date: 2020-11-05 4 | 5 | ## Status 6 | 7 | 2020-11-05 proposed 8 | 9 | ## Context 10 | 11 | Context here... 12 | 13 | ## Decision 14 | 15 | | branch name | create date | last modified date | duration | 16 | |-------------|-------------|---------------------|------------| 17 | | | | | | 18 | 19 | ## Consequences 20 | 21 | Consequences here... 22 | -------------------------------------------------------------------------------- /docs/adr/README.md: -------------------------------------------------------------------------------- 1 | # Architecture Decision Records 2 | 3 | * [1. api-scan-sql](0001-api-scan-sql.md) 4 | * [2. spring-mvc-to-spring-boot-transform](0002-spring-mvc-to-spring-boot-transform.md) 5 | * [3. api-identify](0003-api-identify.md) 6 | * [4. handidraw-graphviz](0004-handidraw-graphviz.md) 7 | * [5. evaluate-api](0005-evaluate-api.md) 8 | * [6. support-adapter-to-cli-framework](0006-support-adapter-to-cli-framework.md) 9 | * [7. practise-go-patterns-in-coca](0007-practise-go-patterns-in-coca.md) 10 | * [8. testable-evaluate](0008-testable-evaluate.md) 11 | * [9. git-tell-file-history](0009-git-tell-file-history.md) 12 | * [10. pluginable](0010-pluginable.md) 13 | * [11. module-treemap-visualization](0011-module-treemap-visualization.md) 14 | * [12. check-dependence-usage-for-module-seperate](0012-check-dependence-usage-for-module-seperate.md) 15 | * [13. performance-issue-for-antlar](0013-performance-issue-for-antlar.md) 16 | * [14. improve-cloc-summary](0014-improve-cloc-summary.md) 17 | * [15. light-weight-coca](0015-light-weight-coca.md) 18 | * [16. git-branch-analysis](0016-git-branch-analysis.md) 19 | -------------------------------------------------------------------------------- /docs/compare/.gitignore: -------------------------------------------------------------------------------- 1 | target 2 | -------------------------------------------------------------------------------- /docs/compare/src/main/java/com/compare/PythonIdentApp.java: -------------------------------------------------------------------------------- 1 | package com.compare; 2 | 3 | import org.antlr.v4.runtime.CharStream; 4 | import org.antlr.v4.runtime.CharStreams; 5 | import org.antlr.v4.runtime.CommonTokenStream; 6 | import org.antlr.v4.runtime.tree.ParseTreeWalker; 7 | import pyantlr.PythonLexer; 8 | import pyantlr.PythonParser; 9 | 10 | public class PythonIdentApp { 11 | static void processString(String inputStr) { 12 | CharStream stream = CharStreams.fromString(inputStr);; 13 | PythonLexer lexer = new PythonLexer(stream); 14 | CommonTokenStream tokens = new CommonTokenStream(lexer); 15 | PythonParser parser = new PythonParser(tokens); 16 | PythonParser.RootContext tree = parser.root(); // see the grammar -> 17 | 18 | PythonIdentListener pythonIdentListener = new PythonIdentListener(); 19 | ParseTreeWalker.DEFAULT.walk(pythonIdentListener, tree); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /docs/compare/src/main/java/com/compare/PythonIdentListener.java: -------------------------------------------------------------------------------- 1 | package com.compare; 2 | 3 | import pyantlr.PythonParser; 4 | import pyantlr.PythonParserBaseListener; 5 | 6 | public class PythonIdentListener extends PythonParserBaseListener { 7 | @Override 8 | public void enterSingle_input(PythonParser.Single_inputContext ctx) { 9 | super.enterSingle_input(ctx); 10 | } 11 | 12 | @Override 13 | public void enterClassdef(PythonParser.ClassdefContext ctx) { 14 | System.out.println(ctx.name().getText()); 15 | super.enterClassdef(ctx); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /docs/compare/src/main/java/com/compare/TsIdentApp.java: -------------------------------------------------------------------------------- 1 | package com.compare; 2 | 3 | import org.antlr.v4.runtime.CharStream; 4 | import org.antlr.v4.runtime.CharStreams; 5 | import org.antlr.v4.runtime.CommonTokenStream; 6 | import org.antlr.v4.runtime.tree.ParseTreeWalker; 7 | import pyantlr.PythonLexer; 8 | import pyantlr.PythonParser; 9 | import tsantlr.TypeScriptLexer; 10 | import tsantlr.TypeScriptParser; 11 | 12 | public class TsIdentApp { 13 | static void processString(String inputStr) { 14 | CharStream stream = CharStreams.fromString(inputStr);; 15 | TypeScriptLexer lexer = new TypeScriptLexer(stream); 16 | CommonTokenStream tokens = new CommonTokenStream(lexer); 17 | TypeScriptParser parser = new TypeScriptParser(tokens); 18 | TypeScriptParser.ProgramContext tree = parser.program(); 19 | 20 | TsIdentListener listener = new TsIdentListener(); 21 | ParseTreeWalker.DEFAULT.walk(listener, tree); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /docs/compare/src/main/java/com/compare/TsIdentListener.java: -------------------------------------------------------------------------------- 1 | package com.compare; 2 | 3 | import tsantlr.TypeScriptParser; 4 | import tsantlr.TypeScriptParserBaseListener; 5 | 6 | public class TsIdentListener extends TypeScriptParserBaseListener { 7 | @Override 8 | public void enterClassDeclaration(TypeScriptParser.ClassDeclarationContext ctx) { 9 | super.enterClassDeclaration(ctx); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /docs/compare/src/main/java/com/compare/main.java: -------------------------------------------------------------------------------- 1 | package com.compare; 2 | 3 | public class main { 4 | public static void main(String[] args) { 5 | 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /docs/compare/src/main/java/pyantlr/PythonBaseParser.java: -------------------------------------------------------------------------------- 1 | package pyantlr; 2 | 3 | import org.antlr.v4.runtime.Parser; 4 | import org.antlr.v4.runtime.TokenStream; 5 | 6 | public abstract class PythonBaseParser extends Parser 7 | { 8 | public PythonVersion Version = PythonVersion.Autodetect; 9 | 10 | protected PythonBaseParser(TokenStream input) { 11 | super(input); 12 | } 13 | 14 | protected boolean CheckVersion(int version) { 15 | return Version == PythonVersion.Autodetect || version == Version.getValue(); 16 | } 17 | 18 | protected void SetVersion(int requiredVersion) { 19 | if (requiredVersion == 2) { 20 | Version = PythonVersion.Python2; 21 | } else if (requiredVersion == 3) { 22 | Version = PythonVersion.Python3; 23 | } 24 | } 25 | } 26 | 27 | -------------------------------------------------------------------------------- /docs/compare/src/main/java/pyantlr/PythonVersion.java: -------------------------------------------------------------------------------- 1 | package pyantlr; 2 | 3 | public enum PythonVersion { 4 | Autodetect(0), 5 | Python2(2), 6 | Python3(3); 7 | 8 | private final int value; 9 | 10 | PythonVersion(int value) { 11 | this.value = value; 12 | } 13 | 14 | public int getValue() { 15 | return value; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /docs/images/changes.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phodal/coca/ba6db6c24a138a6799d6784b7b884349d73c98a4/docs/images/changes.png -------------------------------------------------------------------------------- /docs/images/model.sketch: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phodal/coca/ba6db6c24a138a6799d6784b7b884349d73c98a4/docs/images/model.sketch -------------------------------------------------------------------------------- /docs/stories/1nDSIHPWg-method-call-to-story.feature: -------------------------------------------------------------------------------- 1 | # id: 1nDSIHPWg 2 | # startDate: 2020-01-09T15:32:29Z 3 | # endDate: 2020-01-09T15:32:29Z 4 | # priority: 5 | # status: 6 | # author: 7 | # title: method call to story 8 | # language: zh-CN 9 | @math 10 | 功能:method call to story 11 | 12 | 场景: 13 | 假设 我已经有了所有的 method call 14 | 当 我执行 `coca story` 时 15 | 那么 我应该得到一个故事 16 | -------------------------------------------------------------------------------- /docs/stories/4c02dVfZg-NLP-from-database-Schema.feature: -------------------------------------------------------------------------------- 1 | # id: 4c02dVfZg 2 | # startDate: 2019-12-15T01:18:59Z 3 | # endDate: 2019-12-15T01:18:59Z 4 | # priority: 5 | # status: 6 | # author: 7 | # title: NLP from database Schema 8 | # language: zh-CN 9 | @math 10 | 功能:NLP from database Schema 11 | 12 | 场景: 13 | 假设: 14 | 当: 15 | 并且: 16 | 那么: 17 | -------------------------------------------------------------------------------- /docs/stories/EPwMwfLWg-online-github-project-analysis.feature: -------------------------------------------------------------------------------- 1 | # id: EPwMwfLWg 2 | # startDate: 2020-01-02T02:20:53Z 3 | # endDate: 2020-01-02T02:20:53Z 4 | # priority: 5 | # status: 6 | # author: 7 | # title: online github project analysis 8 | # language: zh-CN 9 | @math 10 | 功能:online github project analysis 11 | 12 | 场景: 13 | 假设: 14 | 当: 15 | 并且: 16 | 那么: 17 | -------------------------------------------------------------------------------- /docs/stories/MomaHFBWg-Code-Complexity-by-files.feature: -------------------------------------------------------------------------------- 1 | # id: MomaHFBWg 2 | # startDate: 2019-12-16T23:22:44Z 3 | # endDate: 2019-12-16T23:22:44Z 4 | # priority: 5 | # status: 6 | # author: 7 | # title: Code Complexity by files 8 | # language: zh-CN 9 | @math 10 | 功能:Code Complexity by files 11 | 12 | 场景: 13 | 假设: 14 | 当: 15 | 并且: 16 | 那么: 17 | -------------------------------------------------------------------------------- /docs/stories/ayGA3GfZR-NLP-from-method-Name.feature: -------------------------------------------------------------------------------- 1 | # id: ayGA3GfZR 2 | # startDate: 2019-12-14T12:30:55Z 3 | # endDate: 2019-12-15T01:20:26Z 4 | # priority: 5 | # status: done 6 | # author: phodal 7 | # title: NLP from method Name 8 | # language: zh-CN 9 | @math 10 | 功能:NLP from method Name 11 | 12 | 场景: 13 | 假设: 14 | 当: 15 | 并且: 16 | 那么: 17 | -------------------------------------------------------------------------------- /docs/stories/yXqVVzYWR-suggest-to-design-pattern-api.feature: -------------------------------------------------------------------------------- 1 | # id: yXqVVzYWR 2 | # startDate: 2019-12-25T11:44:27Z 3 | # endDate: 2019-12-25T11:44:27Z 4 | # priority: 5 | # status: 6 | # author: 7 | # title: suggest to design pattern api 8 | # language: zh-CN 9 | @math 10 | 功能:suggest to design pattern api 11 | 12 | 场景: 当我的代码中存在一些特定的场景,我希望能提示我用设计模式解决 13 | 假设 项目某个类的在多个 constructor 14 | 当 我执行 coca suggest 15 | 那么 我应该能看到建议我使用工厂模式 16 | -------------------------------------------------------------------------------- /languages/README.md: -------------------------------------------------------------------------------- 1 | ``` 2 | antlr -Dlanguage=Go -visitor -listener -lib . JavaParser.g4 3 | ``` 4 | 5 | 6 | -------------------------------------------------------------------------------- /languages/g4/RefactorMethodSignatureParser.g4: -------------------------------------------------------------------------------- 1 | parser grammar RefactorMethodSignatureParser; 2 | 3 | options { tokenVocab=AspectJLexer; } 4 | 5 | import JavaParser; 6 | 7 | classNameOrInterface 8 | : (IDENTIFIER | '*' | '.' | '..')+ ('[' ']')* 9 | ; 10 | -------------------------------------------------------------------------------- /languages/python/python_base_parser.go: -------------------------------------------------------------------------------- 1 | package parser 2 | 3 | import "github.com/antlr/antlr4/runtime/Go/antlr/v4" 4 | 5 | var ( 6 | Autodetect = 0 7 | Python2 = 2 8 | Python3 = 3 9 | ) 10 | 11 | type PythonBaseParser struct { 12 | *antlr.BaseParser 13 | Version int 14 | } 15 | 16 | func (p *PythonBaseParser) CheckVersion(ver int) bool { 17 | return p.Version == Autodetect || p.Version == ver 18 | } 19 | 20 | func (p *PythonBaseParser) SetVersion(ver int) { 21 | if ver == 2 { 22 | p.Version = Python2 23 | } else if ver == 3 { 24 | p.Version = Python3 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /pkg/adapter/cocafile/file_analysis_helper_test.go: -------------------------------------------------------------------------------- 1 | package cocafile 2 | 3 | import ( 4 | "github.com/antlr/antlr4/runtime/Go/antlr/v4" 5 | "github.com/modernizing/coca/pkg/infrastructure/ast/ast_java" 6 | "github.com/modernizing/coca/pkg/infrastructure/ast/ast_java/java_identify" 7 | . "github.com/onsi/gomega" 8 | "testing" 9 | ) 10 | 11 | func TestJavaCallApp_ProcessStringWorks(t *testing.T) { 12 | g := NewGomegaWithT(t) 13 | parser := ast_java.ProcessJavaString(` 14 | package com.phodal.coca.analysis.identifier.model; 15 | 16 | public class DataClass { 17 | private String date; 18 | 19 | public String getDate() { 20 | return date; 21 | } 22 | } 23 | 24 | `) 25 | 26 | context := parser.CompilationUnit() 27 | listener := java_identify.NewJavaIdentifierListener() 28 | 29 | antlr.NewParseTreeWalker().Walk(listener, context) 30 | 31 | identifiers := listener.GetNodes() 32 | g.Expect(identifiers[0].NodeName).To(Equal("DataClass")) 33 | } 34 | -------------------------------------------------------------------------------- /pkg/adapter/shell/git.go: -------------------------------------------------------------------------------- 1 | package shell 2 | 3 | import ( 4 | "fmt" 5 | "log" 6 | "os/exec" 7 | "strconv" 8 | "strings" 9 | ) 10 | 11 | func RunGitGetLog(line int, fileName string) string { 12 | // git log -1 -L2:README.md --pretty="format:[%h] %aN %ad %s" --date=short 13 | historyArgs := []string{"log", "-1", "-L" + strconv.Itoa(line) + ":" + fileName, "--pretty=\"format:[%h] %aN %ad %s\"", "--date=short"} 14 | cmd := exec.Command("git", historyArgs...) 15 | out, err := cmd.CombinedOutput() 16 | if err != nil { 17 | fmt.Println(string(out)) 18 | log.Fatalf("cmd.Run() failed with %s\n", err) 19 | } 20 | 21 | split := strings.Split(string(out), "\n") 22 | output := split[0] + "\n " 23 | return output 24 | } 25 | -------------------------------------------------------------------------------- /pkg/application/analysis/app_concept/abstract_analysis_app.go: -------------------------------------------------------------------------------- 1 | package app_concept 2 | 3 | import "github.com/modernizing/coca/pkg/domain/core_domain" 4 | 5 | type AbstractAnalysisApp interface { 6 | Analysis(code string, path string) core_domain.CodeContainer 7 | IdentAnalysis(s string, file string) []core_domain.CodeMember 8 | SetExtensions(extension interface{}) 9 | AnalysisPackageManager(path string) core_domain.CodePackageInfo 10 | } 11 | -------------------------------------------------------------------------------- /pkg/application/analysis/goapp/go_ident_app_test.go: -------------------------------------------------------------------------------- 1 | package goapp 2 | 3 | import ( 4 | . "github.com/onsi/gomega" 5 | "io/ioutil" 6 | "testing" 7 | ) 8 | 9 | func Test_ProcessPackage(t *testing.T) { 10 | t.Parallel() 11 | g := NewGomegaWithT(t) 12 | 13 | code, _ := ioutil.ReadFile("../../../../pkg/domain/core_domain/code_data_struct.go") 14 | app := &GoIdentApp{} 15 | results := app.Analysis(string(code), "domain") 16 | g.Expect(len(results.DataStructures)).To(Equal(1)) 17 | } 18 | 19 | func Test_IdentDSMember(t *testing.T) { 20 | t.Parallel() 21 | g := NewGomegaWithT(t) 22 | 23 | code, _ := ioutil.ReadFile("../../../../pkg/domain/core_domain/code_data_struct.go") 24 | app := &GoIdentApp{} 25 | results := app.IdentAnalysis(string(code), "file") 26 | g.Expect(results[0].ID).To(Equal("core_domain::CodeDataStruct")) 27 | } 28 | 29 | func Test_ShouldGetModuleNameFromModFile(t *testing.T) { 30 | t.Parallel() 31 | g := NewGomegaWithT(t) 32 | 33 | app := &GoIdentApp{} 34 | packageManager := app.AnalysisPackageManager("../../../..") 35 | 36 | g.Expect(packageManager.ProjectName).To(Equal("github.com/modernizing/coca")) 37 | } 38 | -------------------------------------------------------------------------------- /pkg/application/analysis/javaapp/java_identifier_app.go: -------------------------------------------------------------------------------- 1 | package javaapp 2 | 3 | import ( 4 | "github.com/antlr/antlr4/runtime/Go/antlr/v4" 5 | "github.com/modernizing/coca/pkg/adapter/cocafile" 6 | "github.com/modernizing/coca/pkg/domain/core_domain" 7 | "github.com/modernizing/coca/pkg/infrastructure/ast/ast_java" 8 | "github.com/modernizing/coca/pkg/infrastructure/ast/ast_java/java_identify" 9 | ) 10 | 11 | type JavaIdentifierApp struct { 12 | } 13 | 14 | func NewJavaIdentifierApp() JavaIdentifierApp { 15 | return JavaIdentifierApp{} 16 | } 17 | 18 | func (j *JavaIdentifierApp) AnalysisPath(codeDir string) []core_domain.CodeDataStruct { 19 | files := cocafile.GetJavaFiles(codeDir) 20 | return j.AnalysisFiles(files) 21 | } 22 | 23 | func (j *JavaIdentifierApp) AnalysisFiles(files []string) []core_domain.CodeDataStruct { 24 | var nodeInfos []core_domain.CodeDataStruct = nil 25 | 26 | for _, file := range files { 27 | parser := ast_java.ProcessJavaFile(file) 28 | context := parser.CompilationUnit() 29 | 30 | listener := java_identify.NewJavaIdentifierListener() 31 | 32 | antlr.NewParseTreeWalker().Walk(listener, context) 33 | 34 | identifiers := listener.GetNodes() 35 | nodeInfos = append(nodeInfos, identifiers...) 36 | } 37 | 38 | return nodeInfos 39 | } 40 | -------------------------------------------------------------------------------- /pkg/application/analysis/pyapp/testdata/compare/blog_entity.py: -------------------------------------------------------------------------------- 1 | from ddd.shared.domain_model import DomainModel 2 | 3 | 4 | class Blog(object): 5 | def __init__(self, id, title, content): 6 | self.id = id 7 | self.title = title 8 | self.content = content 9 | 10 | @classmethod 11 | def from_dict(cls, adict): 12 | blog = Blog( 13 | id=adict['id'], 14 | title=adict['title'], 15 | content=adict['content'], 16 | ) 17 | 18 | return blog 19 | 20 | def to_dict(self): 21 | return { 22 | 'id': self.id, 23 | 'title': self.title, 24 | 'content': self.content, 25 | } 26 | 27 | def __eq__(self, other): 28 | return self.to_dict() == other.to_dict() 29 | 30 | DomainModel.register(Blog) 31 | -------------------------------------------------------------------------------- /pkg/application/analysis/pyapp/testdata/grammar/argument.py: -------------------------------------------------------------------------------- 1 | # argument 2 | # : test (comp_for | ASSIGN test)? 3 | # | (POWER | STAR) test 4 | # ; 5 | 6 | # test 7 | b(x) 8 | 9 | # test comp_for 10 | b(x for x in a) 11 | 12 | # test ASSIGN test 13 | b(x=i) 14 | 15 | # test COMMA test ASSIGN test COMMA test ASSIGN test 16 | b(z, x=i, y=u) 17 | 18 | # POWER test 19 | b(**z) 20 | 21 | # STAR test 22 | b(*z) 23 | 24 | # test COMMA STAR test COMMA test ASSIGN test 25 | b(y, *z, x=i) 26 | -------------------------------------------------------------------------------- /pkg/application/analysis/pyapp/testdata/grammar/atom.py: -------------------------------------------------------------------------------- 1 | # atom 2 | # : OPEN_PAREN (yield_expr | testlist_comp)? CLOSE_PAREN 3 | # | OPEN_BRACKET testlist_comp? CLOSE_BRACKET 4 | # | OPEN_BRACE dictorsetmaker? CLOSE_BRACE 5 | # | REVERSE_QUOTE testlist COMMA? REVERSE_QUOTE 6 | # | dotted_name 7 | # | ELLIPSIS 8 | # | name 9 | # | PRINT 10 | # | EXEC 11 | # | MINUS? number 12 | # | NONE 13 | # | STRING+ 14 | # ; 15 | 16 | # OPEN_PAREN CLOSE_PAREN 17 | () 18 | 19 | # OPEN_PAREN yield_expr CLOSE_PAREN 20 | def f(): 21 | (yield) 22 | 23 | # OPEN_PAREN testlist_comp CLOSE_PAREN 24 | (x, a, q == 1) 25 | 26 | # OPEN_BRACKET CLOSE_BRACKET 27 | [] 28 | 29 | # OPEN_BRACKET testlist_comp CLOSE_BRACKET 30 | [1, 3, b, p == 1] 31 | 32 | # OPEN_BRACE CLOSE_BRACE 33 | {} 34 | 35 | # OPEN_BRACE dictorsetmaker CLOSE_BRACE 36 | {x : y for x, y in a} 37 | 38 | # dotted_name 39 | b.a 40 | 41 | # ELLIPSIS 42 | ... 43 | 44 | # name 45 | f 46 | 47 | # number 48 | 90 49 | 50 | # MINUS number 51 | -1 52 | 53 | # NONE 54 | None 55 | 56 | # STRING 57 | "12312313" 58 | 59 | # STRING STRING 60 | "1231231" "123151" 61 | -------------------------------------------------------------------------------- /pkg/application/analysis/pyapp/testdata/grammar/class.py: -------------------------------------------------------------------------------- 1 | class foo: 2 | pass 3 | -------------------------------------------------------------------------------- /pkg/application/analysis/pyapp/testdata/grammar/class_or_func_def_stmt.py: -------------------------------------------------------------------------------- 1 | # class_or_func_def_stmt: decorator+ (classdef | funcdef); 2 | 3 | # decorator classdef 4 | @decorator 5 | class foo: 6 | pass 7 | 8 | # decorator decorator funcdef 9 | @accepts(int,int) 10 | @returns(float) 11 | def bar(low,high): 12 | pass 13 | -------------------------------------------------------------------------------- /pkg/application/analysis/pyapp/testdata/grammar/classdef.py: -------------------------------------------------------------------------------- 1 | # classdef: CLASS name (OPEN_PAREN arglist? CLOSE_PAREN)? COLON suite 2 | 3 | # CLASS NAME COLON suite 4 | class foo: pass 5 | 6 | # CLASS NAME OPEN_PAREN CLOSE_PAREN COLON suite 7 | class bar(): pass 8 | 9 | # CLASS NAME OPEN_PAREN arglist CLOSE_PAREN COLON suite 10 | class baz(foo): 11 | pass 12 | -------------------------------------------------------------------------------- /pkg/application/analysis/pyapp/testdata/grammar/comprehension.py: -------------------------------------------------------------------------------- 1 | # comp_for 2 | # : FOR exprlist IN logical_test comp_iter? 3 | # ; 4 | # 5 | # comp_iter 6 | # : comp_for 7 | # | IF test comp_iter? 8 | # ; 9 | 10 | # FOR exprlist IN logical_test 11 | [x for x in a] 12 | 13 | # FOR exprlist IN logical_test comp_for 14 | [x for x in a for a in k] 15 | 16 | # FOR exprlist IN logical_test IF test 17 | [x for x in a if x == 1] 18 | 19 | # FOR exprlist IN logical_test IF test IF test 20 | [x for x in a if x == 1 if x != 9] 21 | 22 | # FOR exprlist IN logical_test IF test comp_for 23 | [x for x in a if x == 1 for a in q] 24 | -------------------------------------------------------------------------------- /pkg/application/analysis/pyapp/testdata/grammar/def_parameters.py: -------------------------------------------------------------------------------- 1 | # def_parameters: def_parameter (COMMA def_parameter)*; 2 | # def_parameter: named_parameter (ASSIGN test)?; 3 | # named_parameter: NAME (COLON test)?; 4 | 5 | # NAME COLON test 6 | def single_typed(x: int): pass 7 | 8 | # NAME COLON test ASSIGN test 9 | def single_default_typed(x: int = 4): pass 10 | 11 | # NAME COMMA NAME ASSIGN test 12 | def second_default(x, y = 4): pass 13 | -------------------------------------------------------------------------------- /pkg/application/analysis/pyapp/testdata/grammar/dictorsetmaker.py: -------------------------------------------------------------------------------- 1 | # dictorsetmaker 2 | # : (test COLON test | POWER expr) (COMMA (test COLON test | POWER expr))* COMMA? // key_datum_list 3 | # | test COLON test comp_for // dict_comprehension 4 | # | testlist_comp 5 | # ; 6 | 7 | # test COLON test 8 | {d : y} 9 | 10 | # POWER expr 11 | {**x} 12 | 13 | # test COLON test COMMA test COLON test 14 | {d : y, x : z} 15 | 16 | # test COLON test COMMA test COLON test COMMA 17 | {d : y, x : z,} 18 | 19 | # POWER expr COMMA test COLON test 20 | {**x, d : y} 21 | 22 | # test COLON test COMMA POWER expr 23 | {d : y, **x} 24 | 25 | # test COLON test comp_for 26 | {d : y for d, y in x} 27 | 28 | # testlist_comp 29 | {x, q, y} 30 | -------------------------------------------------------------------------------- /pkg/application/analysis/pyapp/testdata/grammar/expr.py: -------------------------------------------------------------------------------- 1 | # expr 2 | # : AWAIT? atom trailer* 3 | # | expr op=POWER expr 4 | # | op=(ADD | MINUS | NOT_OP) expr 5 | # | expr op=(STAR | DIV | MOD | IDIV | AT) expr 6 | # | expr op=(ADD | MINUS) expr 7 | # | expr op=(LEFT_SHIFT | RIGHT_SHIFT) expr 8 | # | expr op=AND_OP expr 9 | # | expr op=XOR expr 10 | # | expr op=OR_OP expr 11 | # ; 12 | 13 | # atom 14 | "123" 15 | 16 | # AWAIT atom 17 | await 5 18 | 19 | # atom trailer 20 | "1231".lower() 21 | 22 | # atom trailer trailer 23 | "1231".lower().upper() 24 | 25 | # AWAIT atom trailer trailer 26 | await "1231".lower().upper() 27 | 28 | # expr op=POWER expr op=POWER expr 29 | 2 ** 2 ** 3 30 | 31 | # ADD expr 32 | +6 33 | 34 | # MINUS expr 35 | -6 36 | 37 | # NOT_OP expr 38 | ~6 39 | 40 | # expr STAR expr 41 | 6 * 7 42 | 43 | # expr DIV expr 44 | 6 / 7 45 | 46 | # expr MOD expr 47 | 6 % 8 48 | 49 | # expr IDIV expr 50 | 6 // 7 51 | 52 | # expr AT expr 53 | 6 @ 2 54 | 55 | # expr ADD expr 56 | 6 + 1 57 | 58 | # expr MINUS expr 59 | 7 - 9 60 | 61 | # expr LEFT_SHIFT expr 62 | 8 << 9 63 | 64 | # expr RIGHT_SHIFT expr 65 | 4 >> 1 66 | 67 | # expr op=AND_OP expr 68 | 4 & 6 69 | 70 | # expr op=XOR expr 71 | 4 ^ 7 72 | 73 | # expr op=OR_OP expr 74 | 7 | 1 75 | -------------------------------------------------------------------------------- /pkg/application/analysis/pyapp/testdata/grammar/for_stmt.py: -------------------------------------------------------------------------------- 1 | # for_stmt: ASYNC? FOR exprlist IN testlist COLON suite else_clause? 2 | 3 | # FOR exprlist IN testlist COLON suite 4 | for x in range(1): 5 | pass 6 | 7 | # FOR exprlist IN testlist COLON suite (else_clause)? 8 | for x in range(1): 9 | x 10 | else: 11 | pass 12 | 13 | # async_stmt must be inside async function 14 | async def f(): 15 | # ASYNC for_stmt 16 | async for _ in range(5): 17 | pass 18 | -------------------------------------------------------------------------------- /pkg/application/analysis/pyapp/testdata/grammar/funcdef.py: -------------------------------------------------------------------------------- 1 | # funcdef: ASYNC? DEF name OPEN_PAREN typedargslist? CLOSE_PAREN (ARROW test)? COLON suite 2 | 3 | # DEF NAME OPEN_PAREN CLOSE_PAREN COLON suite 4 | def foo(): pass 5 | 6 | # ASYNC DEF NAME OPEN_PAREN typedargslist? CLOSE_PAREN COLON suite 7 | async def bar(one): pass 8 | 9 | # DEF NAME OPEN_PAREN typedargslist? CLOSE_PAREN ARROW test COLON suite 10 | def baz(one, two) -> int: pass 11 | -------------------------------------------------------------------------------- /pkg/application/analysis/pyapp/testdata/grammar/if_stmt.py: -------------------------------------------------------------------------------- 1 | # if_stmt: IF cond=test COLON suite elif_clause* else_clause? 2 | 3 | # IF test COLON suite 4 | if x == 5: pass 5 | 6 | # IF test COLON suite elif_clause 7 | if x == 4: 8 | pass 9 | elif x == 3: 10 | pass 11 | 12 | # IF test COLON suite else_clause 13 | if x == 7: 14 | pass 15 | else: 16 | pass 17 | 18 | # IF test COLON suite elif_clause elif_clause else_clause 19 | if x == 4: 20 | pass 21 | elif x == 3: 22 | pass 23 | else: 24 | pass 25 | -------------------------------------------------------------------------------- /pkg/application/analysis/pyapp/testdata/grammar/logical_test.py: -------------------------------------------------------------------------------- 1 | # logical_test 2 | # : comparison 3 | # | NOT logical_test 4 | # | logical_test op=AND logical_test 5 | # | logical_test op=OR logical_test 6 | # ; 7 | # 8 | # comparison 9 | # : comparison (LESS_THAN | GREATER_THAN | EQUALS | GT_EQ | LT_EQ | NOT_EQ_1 | NOT_EQ_2 | optional=NOT? IN | IS optional=NOT?) comparison 10 | # | expr 11 | # ; 12 | 13 | # expr EQUALS expr 14 | a == b 15 | 16 | # not expr 17 | not a 18 | 19 | # expr AND expr 20 | a and b 21 | 22 | # expr OR expr 23 | a or b 24 | 25 | # expr LESS_THAN expr 26 | a < b 27 | 28 | # expr GREATER_THAN expr 29 | a > b 30 | 31 | # expr GT_EQ expr 32 | a >= b 33 | 34 | # expr LT_EQ expr 35 | a <= b 36 | 37 | # expr NOT_EQ_2 expr 38 | a != b 39 | 40 | # expr IN expr 41 | a in b 42 | 43 | # expr NOT IN expr 44 | a not in b 45 | 46 | # expr IS expr 47 | a is b 48 | 49 | # expr IS NOT expr 50 | a is not b 51 | -------------------------------------------------------------------------------- /pkg/application/analysis/pyapp/testdata/grammar/simple_stmt.py: -------------------------------------------------------------------------------- 1 | # simple_stmt: small_stmt (SEMI_COLON small_stmt)* SEMI_COLON? (NEWLINE | EOF) 2 | 3 | # small_stmt NEWLINE 4 | x = 5 5 | 6 | # small_stmt SEMI_COLON small_stmt NEWLINE 7 | x = 5 ; y = 7 8 | 9 | # small_stmt SEMI_COLON NEWLINE 10 | x = 5 ; 11 | 12 | # small_stmt SEMI_COLON small_stmt SEMI_COLON small_stmt SEMI_COLON small_stmt SEMI_COLON EOF 13 | x = 5 ; y = 7 ; z = 9 ; -------------------------------------------------------------------------------- /pkg/application/analysis/pyapp/testdata/grammar/small_stmt.py: -------------------------------------------------------------------------------- 1 | # del_stmt: DEL exprlist 2 | 3 | del x, d[1], await f 4 | 5 | # pass_stmt: PASS 6 | for i in u: pass 7 | 8 | # break_stmt: BREAK 9 | for i in u: break 10 | 11 | # continue_stmt: CONTINUE 12 | for i in u: continue 13 | 14 | # return_stmt: RETURN testlist? 15 | def f(): 16 | # RETURN 17 | return 18 | def g(): 19 | # RETURN testlist 20 | return 1, 3 21 | 22 | # [Python 3] raise_stmt: RAISE (test (FROM test)?)? 23 | 24 | # RAISE test FROM test 25 | raise a from b 26 | 27 | # RAISE test 28 | raise a 29 | 30 | try: 31 | a 32 | except: 33 | # RAISE 34 | raise 35 | 36 | # global_stmt: GLOBAL name (COMMA name)* 37 | 38 | # GLOBAL name 39 | global a 40 | 41 | # GLOBAL name COMMA name 42 | global a, b 43 | 44 | # assert_stmt: ASSERT test (COMMA test)? 45 | 46 | # ASSERT test 47 | assert a 48 | 49 | # ASSERT test COMMA test 50 | assert a, b 51 | 52 | # nonlocal_stmt: NONLOCAL name (COMMA name)* 53 | 54 | # NONLOCAL name 55 | nonlocal a 56 | 57 | # NONLOCAL name (COMMA name) 58 | nonlocal a, v 59 | -------------------------------------------------------------------------------- /pkg/application/analysis/pyapp/testdata/grammar/subscript.py: -------------------------------------------------------------------------------- 1 | # subscript 2 | # : ELLIPSIS 3 | # | test 4 | # | test? COLON test? sliceop? 5 | # ; 6 | # 7 | # sliceop 8 | # : COLON test? 9 | # ; 10 | 11 | # ELLIPSIS 12 | b[...] 13 | 14 | # test 15 | b[a] 16 | 17 | # COLON 18 | b[:] 19 | 20 | # test COLON 21 | b[a:] 22 | 23 | # COLON test 24 | b[:a] 25 | 26 | # test COLON test 27 | b[a:a] 28 | 29 | # COLON COLON 30 | b[::] 31 | 32 | # COLON COLON test 33 | b[::-1] 34 | 35 | # test COLON COLON test 36 | b[a::2] 37 | 38 | # COLON test COLON test 39 | b[:a:2] 40 | 41 | # test COLON test COLON test 42 | b[1:a:2] 43 | -------------------------------------------------------------------------------- /pkg/application/analysis/pyapp/testdata/grammar/test.py: -------------------------------------------------------------------------------- 1 | # test 2 | # : logical_test (IF logical_test ELSE test)? 3 | # | LAMBDA varargslist? COLON test 4 | # ; 5 | 6 | # logical_test 7 | x == y 8 | 9 | # logical_test IF logical_test ELSE test 10 | x == y if z == b else a == u 11 | 12 | # LAMBDA COLON test 13 | lambda: a 14 | 15 | # LAMBDA varargslist COLON test 16 | lambda x, y: a 17 | -------------------------------------------------------------------------------- /pkg/application/analysis/pyapp/testdata/grammar/testlist_comp.py: -------------------------------------------------------------------------------- 1 | # testlist_comp 2 | # : (test | star_expr) (comp_for | (COMMA (test | star_expr))* COMMA?) 3 | # ; 4 | 5 | # test 6 | [x] 7 | 8 | # star_expr comp_for 9 | [z for z in a] 10 | 11 | # test COMMA star_expr COMMA 12 | [x, *a,] 13 | 14 | # star_expr COMMA test COMMA star_expr 15 | [*u, a, *i] 16 | -------------------------------------------------------------------------------- /pkg/application/analysis/pyapp/testdata/grammar/tokens.py: -------------------------------------------------------------------------------- 1 | DECIMAL = 0000000000 2 | DECIMAL = 1234567890 3 | OCT_1 = 0o01234567 4 | OCT_2 = 0O01234567 5 | HEX_1 = 0x0123456789abcdef 6 | HEX_2 = 0X0123456789ABCDEF 7 | BIN_1 = 0b01 8 | BIN_1 = 0B01 9 | IMAG_1 = 0123456789.0123456789j 10 | IMAG_2 = 0123456789J 11 | FLOAT_1 = 0123456789.e1234567890 12 | FLOAT_2 = .0123456789E1234567890 13 | 14 | LINE_JOIN_EXPR = 2 + \ 15 | 2 16 | 17 | SHORT_STRING_1 = 'a \'\\ b' 18 | SHORT_STRING_2 = "a \"\\ b" 19 | LONG_STRING_1 = b""" asdf " qwer 20 | zxcv 21 | """ 22 | LONG_STRING_1 = r''' aasdf ' qwer 23 | zxcv 24 | ''' 25 | STRING_WITH_LINE_JOIND = "a \ 26 | b" 27 | 28 | # COMMENT 29 | 30 | -------------------------------------------------------------------------------- /pkg/application/analysis/pyapp/testdata/grammar/trailer.py: -------------------------------------------------------------------------------- 1 | # trailer 2 | # : OPEN_PAREN (argument (COMMA argument)* COMMA?)? CLOSE_PAREN 3 | # | OPEN_BRACKET subscript (COMMA subscript)* COMMA? CLOSE_BRACKET 4 | # | DOT name 5 | # ; 6 | 7 | # DOT name 8 | a.b 9 | 10 | # OPEN_PAREN CLOSE_PAREN 11 | x() 12 | 13 | # OPEN_PAREN argument CLOSE_PAREN 14 | x(a) 15 | 16 | # OPEN_PAREN argument COMMA argument COMMA CLOSE_PAREN 17 | x(a, b,) 18 | 19 | # OPEN_PAREN argument COMMA argument COMMA argument CLOSE_PAREN 20 | x(a, b, c) 21 | 22 | # OPEN_BRACKET subscript CLOSE_BRACKET 23 | x[a] 24 | 25 | # OPEN_BRACKET subscript COMMA subscript COMMA CLOSE_BRACKET 26 | x[a, b,] 27 | 28 | # OPEN_BRACKET subscript COMMA subscript COMMA subscript CLOSE_BRACKET 29 | x[a, b, c] -------------------------------------------------------------------------------- /pkg/application/analysis/pyapp/testdata/grammar/try_stmt.py: -------------------------------------------------------------------------------- 1 | # try_stmt: TRY COLON suite (except_clause+ else_clause? finaly_clause? | finaly_clause) 2 | 3 | # TRY COLON suite except_clause 4 | try: 5 | pass 6 | except: 7 | pass 8 | 9 | # TRY COLON suite except_clause except_clause else_clause 10 | try: 11 | pass 12 | except Exception as ex: 13 | pass 14 | except: 15 | pass 16 | else: 17 | pass 18 | 19 | # TRY COLON suite except_clause finaly_clause 20 | try: 21 | pass 22 | except Exception: 23 | pass 24 | finally: 25 | pass 26 | 27 | # TRY COLON suite finaly_clause 28 | try: 29 | pass 30 | finally: 31 | pass 32 | -------------------------------------------------------------------------------- /pkg/application/analysis/pyapp/testdata/grammar/typedargslist.py: -------------------------------------------------------------------------------- 1 | # typedargslist 2 | # : (def_parameters COMMA)? (args (COMMA def_parameters)? (COMMA kwargs)? | kwargs) 3 | # | def_parameters 4 | # ; 5 | 6 | # def_parameters COMMA 7 | def single(x, *, i): pass 8 | 9 | # def_parameters COMMA kwargs 10 | def f1(x, y, **z): pass 11 | 12 | # def_parameters COMMA args COMMA def_parameters COMMA kwargs COMMA 13 | def f1(x, y, *z: int, a, b, **c: int,): pass 14 | 15 | # def_parameters COMMA args 16 | def f1(x, y, *z): pass 17 | 18 | -------------------------------------------------------------------------------- /pkg/application/analysis/pyapp/testdata/grammar/varargslist.py: -------------------------------------------------------------------------------- 1 | # varargslist 2 | # : (vardef_parameters COMMA)? (varargs (COMMA vardef_parameters)? (COMMA varkwargs)? | varkwargs) COMMA? 3 | # | vardef_parameters COMMA? 4 | # ; 5 | # 6 | # vardef_parameters 7 | # : vardef_parameter (COMMA vardef_parameter)* 8 | # ; 9 | # 10 | # vardef_parameter 11 | # : name (ASSIGN test)? 12 | # ; 13 | # 14 | # varargs 15 | # : STAR name 16 | # ; 17 | # 18 | # varkwargs 19 | # : POWER name 20 | # ; 21 | 22 | # vardef_parameters COMMA 23 | # NAME COMMA 24 | lambda x,: 5 25 | 26 | # vardef_parameters COMMA 27 | # NAME COMMA STAR COMMA NAME COMMA 28 | lambda x, *, y,: 5 29 | 30 | # vardef_parameters 31 | # NAME COMMA STAR COMMA NAME ASSIGN test 32 | lambda x, *, y=7: 5 33 | 34 | # varargs 35 | lambda *y: 8 36 | 37 | # varargs COMMA vardef_parameters COMMA 38 | lambda *y, z: 8 39 | 40 | # vardef_parameters COMMA varargs COMMA vardef_parameters COMMA 41 | lambda a, b, *y, z: 8 42 | 43 | # vardef_parameters COMMA varargs COMMA vardef_parameters COMMA varkwargs 44 | lambda a, b, *y, z, **k: 8 45 | 46 | # varkwargs 47 | lambda **z: 8 48 | 49 | # vardef_parameters COMMA varkwargs 50 | lambda a, b, c, **k: 8 51 | -------------------------------------------------------------------------------- /pkg/application/analysis/pyapp/testdata/grammar/while_stmt.py: -------------------------------------------------------------------------------- 1 | # while_stmt: WHILE test COLON suite else_clause? 2 | 3 | # WHILE test COLON suite 4 | while x == 3: 5 | x += 1 6 | 7 | # WHILE test COLON suite else_clause 8 | while x == 3: 9 | x += 1 10 | else: 11 | pass 12 | -------------------------------------------------------------------------------- /pkg/application/analysis/pyapp/testdata/grammar/with_stmt.py: -------------------------------------------------------------------------------- 1 | # with_stmt: ASYNC? WITH with_item (COMMA with_item)* COLON suite 2 | 3 | # WITH with_item COLON suite 4 | with open("with_stmt.py"): 5 | pass 6 | 7 | # WITH with_item COMMA with_item COLON suite 8 | with open("with_stmt.py") as a, open("with_stmt.py") as b: 9 | pass 10 | 11 | # async_stmt must be inside async function 12 | async def f(): 13 | # ASYNC with_stmt 14 | async with open("with_stmt.py") as f: 15 | pass 16 | -------------------------------------------------------------------------------- /pkg/application/analysis/pyapp/testdata/grammar/yield_expr.py: -------------------------------------------------------------------------------- 1 | # yield_expr 2 | # : YIELD yield_arg? 3 | # ; 4 | # 5 | # yield_arg 6 | # : FROM test 7 | # | testlist 8 | # ; 9 | 10 | def f(): 11 | 12 | # YIELD 13 | yield 14 | 15 | # YIELD FROM test 16 | yield from g 17 | 18 | # YIELD testlist 19 | yield x, a, b if x else a 20 | 21 | -------------------------------------------------------------------------------- /pkg/application/api/java_api_app_test.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | import ( 4 | . "github.com/onsi/gomega" 5 | "github.com/modernizing/coca/cocatest/testhelper" 6 | "github.com/modernizing/coca/pkg/domain/core_domain" 7 | "testing" 8 | ) 9 | 10 | func TestJavaCallApp_AnalysisPath(t *testing.T) { 11 | g := NewGomegaWithT(t) 12 | 13 | codePath := "../../../_fixtures/call" 14 | callNodes, identifiersMap, identifiers := testhelper.BuildAnalysisDeps(codePath) 15 | diMap := core_domain.BuildDIMap(identifiers, identifiersMap) 16 | 17 | app := new(JavaApiApp) 18 | restApis := app.AnalysisPath(codePath, callNodes, identifiersMap, diMap) 19 | 20 | g.Expect(len(restApis)).To(Equal(4)) 21 | g.Expect(restApis[0].HttpMethod).To(Equal("POST")) 22 | g.Expect(restApis[0].Uri).To(Equal("/books")) 23 | } -------------------------------------------------------------------------------- /pkg/application/arch/tequila/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Li Xin 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /pkg/application/arch/tequila/merge_viz.go: -------------------------------------------------------------------------------- 1 | package tequila 2 | 3 | import ( 4 | "strings" 5 | ) 6 | 7 | var Level = 7 8 | 9 | var MergeHeaderFunc = func(input string) string { 10 | tmp := strings.Split(input, ".") 11 | if len(tmp) > 1 { 12 | return strings.Join(tmp[0:len(tmp)-1], ".") 13 | } 14 | return input 15 | } 16 | 17 | var MergePackageFunc = func(input string) string { 18 | split := "/" 19 | if !strings.Contains(input, split) { 20 | split = "." 21 | } 22 | if !strings.Contains(input, split) { 23 | split = "::" 24 | } 25 | tmp := strings.Split(input, split) 26 | packageName := tmp[0] 27 | if packageName == input { 28 | packageName = "main" 29 | } 30 | 31 | if len(tmp) > Level { 32 | packageName = strings.Join(tmp[:(Level)], split) 33 | } 34 | 35 | return packageName 36 | } 37 | -------------------------------------------------------------------------------- /pkg/application/concept/concept_analyser_test.go: -------------------------------------------------------------------------------- 1 | package concept 2 | 3 | import ( 4 | "encoding/json" 5 | "github.com/modernizing/coca/cmd/cmd_util" 6 | "github.com/modernizing/coca/pkg/domain/core_domain" 7 | "log" 8 | "path/filepath" 9 | "testing" 10 | 11 | . "github.com/onsi/gomega" 12 | ) 13 | 14 | func TestConceptAnalyser_Analysis(t *testing.T) { 15 | g := NewGomegaWithT(t) 16 | 17 | var parsedDeps []core_domain.CodeDataStruct 18 | analyser := NewConceptAnalyser() 19 | codePath := "../../../_fixtures/call/call_api_test.json" 20 | codePath = filepath.FromSlash(codePath) 21 | 22 | file := cmd_util.ReadFile(codePath) 23 | if file == nil { 24 | log.Fatal("lost file") 25 | } 26 | 27 | _ = json.Unmarshal(file, &parsedDeps) 28 | 29 | counts := analyser.Analysis(&parsedDeps) 30 | 31 | g.Expect(len(counts)).To(Equal(4)) 32 | } 33 | -------------------------------------------------------------------------------- /pkg/application/concept/concept_segmenter.go: -------------------------------------------------------------------------------- 1 | package concept 2 | 3 | import ( 4 | "github.com/iancoleman/strcase" 5 | "regexp" 6 | "strings" 7 | ) 8 | 9 | type ConceptSegmenter struct { 10 | } 11 | 12 | var strMap map[string]int 13 | 14 | func SegmentCamelcase(methodsName []string) map[string]int { 15 | strMap = make(map[string]int) 16 | for _, name := range methodsName { 17 | // get, set 18 | if (strings.HasSuffix("set", name) || strings.HasSuffix("get", name)) && len(name) > 3 { 19 | domainName := name[3:] 20 | if strMap[domainName] == 0 { 21 | strMap[domainName] = 1 22 | } else { 23 | strMap[domainName] = strMap[domainName] + 1 24 | } 25 | } else { 26 | delimited := strcase.ToDelimited(name, '.') 27 | split := strings.Split(delimited, ".") 28 | for _, word := range split { 29 | if FilterString(word) == "" { 30 | continue 31 | } 32 | if strMap[word] == 0 { 33 | strMap[word] = 1 34 | } else { 35 | strMap[word] = strMap[word] + 1 36 | } 37 | } 38 | } 39 | } 40 | 41 | return strMap 42 | } 43 | 44 | func FilterString(str string) string { 45 | var digitCheck = regexp.MustCompile(`^[0-9]+$`) 46 | 47 | if digitCheck.MatchString(str) { 48 | return "" 49 | } 50 | 51 | return strings.TrimSpace(str) 52 | } 53 | -------------------------------------------------------------------------------- /pkg/application/count/count_app.go: -------------------------------------------------------------------------------- 1 | package count 2 | 3 | import ( 4 | "github.com/modernizing/coca/pkg/domain/core_domain" 5 | ) 6 | 7 | func BuildCallMap(parserDeps []core_domain.CodeDataStruct) map[string]int { 8 | var projectMethods = make(map[string]string) 9 | for _, clz := range parserDeps { 10 | clz.BuildStringMethodMap(projectMethods) 11 | } 12 | 13 | // TODO: support identify data class 14 | var callMap = make(map[string]int) 15 | for _, clz := range parserDeps { 16 | for _, method := range clz.Functions { 17 | for _, call := range method.FunctionCalls { 18 | callMethod := call.BuildFullMethodName() 19 | if _, ok := projectMethods[callMethod]; ok { 20 | if callMap[callMethod] == 0 { 21 | callMap[callMethod] = 1 22 | } else { 23 | callMap[callMethod]++ 24 | } 25 | } 26 | } 27 | } 28 | } 29 | 30 | return callMap 31 | } 32 | 33 | -------------------------------------------------------------------------------- /pkg/application/count/count_app_test.go: -------------------------------------------------------------------------------- 1 | package count 2 | 3 | import ( 4 | "encoding/json" 5 | . "github.com/onsi/gomega" 6 | "github.com/modernizing/coca/cmd/cmd_util" 7 | "github.com/modernizing/coca/pkg/domain/core_domain" 8 | "path/filepath" 9 | "testing" 10 | ) 11 | 12 | func TestBuildCallMap(t *testing.T) { 13 | g := NewGomegaWithT(t) 14 | var parsedDeps []core_domain.CodeDataStruct 15 | codePath := "../../../_fixtures/count/call.json" 16 | codePath = filepath.FromSlash(codePath) 17 | file := cmd_util.ReadFile(codePath) 18 | _ = json.Unmarshal(file, &parsedDeps) 19 | 20 | callMap := BuildCallMap(parsedDeps) 21 | 22 | g.Expect(len(callMap)).To(Equal(4)) 23 | g.Expect(callMap["com.phodal.pholedge.book.BookService.createBook"]).To(Equal(1)) 24 | g.Expect(callMap["com.phodal.pholedge.book.BookService.getBookById"]).To(Equal(1)) 25 | g.Expect(callMap["com.phodal.pholedge.book.BookService.getBooksLists"]).To(Equal(1)) 26 | } 27 | -------------------------------------------------------------------------------- /pkg/application/deps/gradle_analysis.go: -------------------------------------------------------------------------------- 1 | package deps 2 | 3 | import ( 4 | "github.com/antlr/antlr4/runtime/Go/antlr/v4" 5 | "github.com/modernizing/coca/cmd/cmd_util" 6 | "github.com/modernizing/coca/pkg/domain/core_domain" 7 | "github.com/modernizing/coca/pkg/infrastructure/ast/ast_groovy" 8 | ) 9 | 10 | func AnalysisGradleFile(path string) []core_domain.CodeDependency { 11 | bytes := cmd_util.ReadFile(path) 12 | return AnalysisGradleString(string(bytes)) 13 | } 14 | 15 | func AnalysisGradleString(str string) []core_domain.CodeDependency { 16 | parser := ast_groovy.ProcessGroovyString(str) 17 | context := parser.CompilationUnit() 18 | listener := ast_groovy.NewGroovyIdentListener() 19 | antlr.NewParseTreeWalker().Walk(listener, context) 20 | 21 | return listener.GetDepsInfo() 22 | } 23 | -------------------------------------------------------------------------------- /pkg/application/evaluate/README.md: -------------------------------------------------------------------------------- 1 | # 分析 2 | 3 | 4 | ## Static 链分析 5 | 6 | ## 可测试性 7 | 8 | ### 测试建议 9 | 10 | 11 | ## Bad Design 12 | 13 | 1. RESTful API in different controller 14 | 2. Untestable 15 | -------------------------------------------------------------------------------- /pkg/application/evaluate/evaluate.go: -------------------------------------------------------------------------------- 1 | package evaluate 2 | 3 | import ( 4 | "github.com/modernizing/coca/pkg/application/evaluate/evaluator" 5 | "github.com/modernizing/coca/pkg/domain/core_domain" 6 | ) 7 | 8 | type Evaluator interface { 9 | Evaluate(result *evaluator.EvaluateModel, node core_domain.CodeDataStruct) 10 | EvaluateList(evaluateModel *evaluator.EvaluateModel, nodes []core_domain.CodeDataStruct, nodeMap map[string]core_domain.CodeDataStruct, identifiers []core_domain.CodeDataStruct) 11 | } 12 | 13 | type Evaluation struct { 14 | Evaluator Evaluator 15 | } 16 | 17 | func (o *Evaluation) Evaluate(result *evaluator.EvaluateModel, node core_domain.CodeDataStruct) { 18 | o.Evaluator.Evaluate(result, node) 19 | } 20 | 21 | func (o *Evaluation) EvaluateList(evaluateModel *evaluator.EvaluateModel, nodes []core_domain.CodeDataStruct, nodeMap map[string]core_domain.CodeDataStruct, identifiers []core_domain.CodeDataStruct) { 22 | o.Evaluator.EvaluateList(evaluateModel, nodes, nodeMap, identifiers) 23 | } 24 | -------------------------------------------------------------------------------- /pkg/application/evaluate/evaluator/controller.go: -------------------------------------------------------------------------------- 1 | package evaluator 2 | 3 | import ( 4 | "fmt" 5 | "github.com/modernizing/coca/pkg/domain/core_domain" 6 | ) 7 | 8 | type Controller struct { 9 | } 10 | 11 | func (Controller) Evaluate(node core_domain.CodeDataStruct) { 12 | fmt.Println("controller") 13 | } 14 | -------------------------------------------------------------------------------- /pkg/application/evaluate/evaluator/empty.go: -------------------------------------------------------------------------------- 1 | package evaluator 2 | 3 | import ( 4 | "github.com/modernizing/coca/pkg/domain/core_domain" 5 | ) 6 | 7 | type Empty struct { 8 | } 9 | 10 | func (Empty) Evaluate(*EvaluateModel, core_domain.CodeDataStruct) { 11 | 12 | } 13 | 14 | func (Empty) EvaluateList(*EvaluateModel, []core_domain.CodeDataStruct, map[string]core_domain.CodeDataStruct, []core_domain.CodeDataStruct) { 15 | 16 | } -------------------------------------------------------------------------------- /pkg/application/evaluate/evaluator/models.go: -------------------------------------------------------------------------------- 1 | package evaluator 2 | 3 | type Nullable struct { 4 | Items []string 5 | } 6 | 7 | type ServiceSummary struct { 8 | LifecycleMap map[string][]string 9 | ReturnTypeMap map[string][]string 10 | RelatedMethod []string 11 | } 12 | 13 | type NormalIssues struct { 14 | } 15 | 16 | type UtilsSummary struct { 17 | } 18 | 19 | type Summary struct { 20 | UtilsCount int 21 | ClassCount int 22 | MethodCount int 23 | NormalMethodCount int 24 | TotalMethodLength int 25 | StaticMethodCount int 26 | MethodLengthStdDeviation float64 27 | MethodNumStdDeviation float64 28 | } 29 | 30 | type EvaluateModel struct { 31 | Nullable Nullable 32 | ServiceSummary ServiceSummary 33 | UtilsSummary UtilsSummary 34 | Summary Summary 35 | } 36 | 37 | func NewEvaluateModel() EvaluateModel { 38 | return EvaluateModel{Nullable: Nullable{Items: nil}} 39 | } 40 | -------------------------------------------------------------------------------- /pkg/application/evaluate/evaluator/util.go: -------------------------------------------------------------------------------- 1 | package evaluator 2 | 3 | import ( 4 | "github.com/modernizing/coca/pkg/domain/core_domain" 5 | ) 6 | 7 | type Util struct { 8 | } 9 | 10 | func (Util) Evaluate(result *EvaluateModel, node core_domain.CodeDataStruct) { 11 | 12 | } 13 | 14 | func (s Util) EvaluateList(evaluateModel *EvaluateModel, nodes []core_domain.CodeDataStruct, nodeMap map[string]core_domain.CodeDataStruct, identifiers []core_domain.CodeDataStruct) { 15 | 16 | } 17 | -------------------------------------------------------------------------------- /pkg/application/git/README.md: -------------------------------------------------------------------------------- 1 | 2 | GitLogs 3 | 4 | ``` 5 | git log --all --date=short --pretty="format:[%h] %aN %ad %s" --numstat --reverse --summary 6 | ``` 7 | 8 | Delete 9 | 10 | ``` 11 | git log --pretty=%H --name-status 12 | ``` 13 | 14 | ``` 15 | git log --pretty=format:"[%h] %aN %ad %s" --reverse --summary --numstat --encoding=UTF-8 --no-renames 16 | ``` 17 | 18 | 19 | 20 | Related Projects: [https://github.com/bast/gitink](https://github.com/bast/gitink) 21 | 22 | 23 | ``` 24 | $ cat example.txt 25 | 26 | [feature] 27 | | 28 | v 29 | x1-----x2 30 | / 31 | c1----c2----m1----c3----c4 32 | \ / ^ 33 | b1----b2----b3 | 34 | ^ ^ [master,HEAD] 35 | | | 36 | [_branch] [branch] 37 | 38 | $ gitink --time-direction=90 --in-file=example.txt | display 39 | ``` 40 | 41 | -------------------------------------------------------------------------------- /pkg/application/git/changelog_test.go: -------------------------------------------------------------------------------- 1 | package git 2 | 3 | import ( 4 | . "github.com/onsi/gomega" 5 | "testing" 6 | ) 7 | 8 | func TestBuildChangeMap(t *testing.T) { 9 | g := NewGomegaWithT(t) 10 | 11 | result := BuildMessageByInput(` 12 | [c24069b] Phodal HUANG 2019-10-25 fix: fix test 13 | 7 0 README.md 14 | 15 | [c24069b] Phodal HUANG 2019-10-25 feat: add README.md 16 | 7 0 README.md 17 | 18 | `) 19 | 20 | buildChangeMap := BuildChangeMap(result) 21 | g.Expect(buildChangeMap["feat"]["README.md"]).To(Equal(1)) 22 | g.Expect(buildChangeMap["fix"]["README.md"]).To(Equal(1)) 23 | } -------------------------------------------------------------------------------- /pkg/application/git/models.go: -------------------------------------------------------------------------------- 1 | package git 2 | 3 | import "time" 4 | 5 | type CodeAgeDisplay struct { 6 | EntityName string 7 | Month string 8 | } 9 | 10 | type TeamSummary struct { 11 | EntityName string 12 | AuthorCount int 13 | RevsCount int 14 | } 15 | 16 | type ProjectInfo struct { 17 | EntityName string 18 | Authors map[string]string 19 | Revs map[string]string 20 | Age time.Time 21 | } 22 | 23 | type GitSummary struct { 24 | Commits int 25 | Entities int 26 | Changes int 27 | Authors int 28 | } 29 | 30 | type CommitMessage struct { 31 | Rev string 32 | Author string 33 | Date string 34 | Message string 35 | Changes []FileChange 36 | } 37 | 38 | type FileChange struct { 39 | Added int 40 | Deleted int 41 | File string 42 | Mode string 43 | } 44 | -------------------------------------------------------------------------------- /pkg/application/refactor/base/models/jmove_struct.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | 4 | type JImport struct { 5 | Name string 6 | StartLine int 7 | StopLine int 8 | } 9 | 10 | type JMoveStruct struct { 11 | JFullIdentifier 12 | 13 | Path string 14 | Deps []JImport 15 | } 16 | -------------------------------------------------------------------------------- /pkg/application/refactor/moveclass/move_class_app_test.go: -------------------------------------------------------------------------------- 1 | package moveclass 2 | 3 | import ( 4 | . "github.com/onsi/gomega" 5 | "os" 6 | "path/filepath" 7 | "testing" 8 | ) 9 | 10 | func TestMoveClassApp(t *testing.T) { 11 | g := NewGomegaWithT(t) 12 | 13 | config := filepath.FromSlash("../../../../_fixtures/refactor/move.config") 14 | path := filepath.FromSlash("../../../../_fixtures/refactor") 15 | 16 | absPath, _ := filepath.Abs(path) 17 | app := NewMoveClassApp(config, filepath.FromSlash(absPath)) 18 | app.Analysis() 19 | app.Refactoring() 20 | 21 | stat, _ := os.Stat(filepath.FromSlash(absPath + "/move/b/ImportForB.java")) 22 | g.Expect(stat.Name()).To(Equal("ImportForB.java")) 23 | 24 | g.Expect(true).To(Equal(true)) 25 | } -------------------------------------------------------------------------------- /pkg/application/refactor/rename/rename_method_test.go: -------------------------------------------------------------------------------- 1 | package unused 2 | 3 | import ( 4 | "github.com/modernizing/coca/cmd/cmd_util" 5 | "github.com/modernizing/coca/cocatest/testhelper" 6 | "github.com/modernizing/coca/pkg/application/analysis/javaapp" 7 | . "github.com/onsi/gomega" 8 | "path/filepath" 9 | "testing" 10 | ) 11 | 12 | func TestRenameMethodApp(t *testing.T) { 13 | g := NewGomegaWithT(t) 14 | 15 | codePath := "../../../../_fixtures/refactor/unused" 16 | configPath := "../../../../_fixtures/refactor/rename.config" 17 | codePath = filepath.FromSlash(codePath) 18 | configPath = filepath.FromSlash(configPath) 19 | 20 | identifierApp := new(javaapp.JavaIdentifierApp) 21 | identifiers := identifierApp.AnalysisPath(codePath) 22 | var classes []string = nil 23 | for _, node := range identifiers { 24 | classes = append(classes, node.Package+"."+node.NodeName) 25 | } 26 | 27 | callApp := javaapp.NewJavaFullApp() 28 | callNodes := callApp.AnalysisPath(codePath, identifiers) 29 | 30 | configBytes := cmd_util.ReadFile(configPath) 31 | RenameMethodApp(callNodes).Refactoring(string(configBytes)) 32 | 33 | newnodes := callApp.AnalysisPath(codePath, identifiers) 34 | g.Expect(newnodes[0].Functions[0].Name).To(Equal("demo")) 35 | 36 | testhelper.ResetGitDir(codePath) 37 | } 38 | -------------------------------------------------------------------------------- /pkg/application/refactor/rename/support/package_info_helper.go: -------------------------------------------------------------------------------- 1 | package support 2 | 3 | import ( 4 | "strings" 5 | ) 6 | 7 | func BuildMethodPackageInfo(name string) *PackageClassInfo { 8 | pkgInfo := &PackageClassInfo{"", "", ""} 9 | split := strings.Split(name, ".") 10 | 11 | pkgInfo.Method = split[len(split)-1] 12 | pkgInfo.Class = split[len(split)-2] 13 | pkgInfo.Package = strings.Join(split[:len(split)-2], ".") 14 | return pkgInfo 15 | } 16 | -------------------------------------------------------------------------------- /pkg/application/refactor/rename/support/package_info_helper_test.go: -------------------------------------------------------------------------------- 1 | package support 2 | 3 | import ( 4 | "reflect" 5 | "testing" 6 | ) 7 | 8 | func TestBuildMethodPackageInfo(t *testing.T) { 9 | tests := []struct { 10 | name string 11 | want *PackageClassInfo 12 | }{ 13 | { 14 | "com.phodal.Coca.hello", 15 | &PackageClassInfo{"com.phodal", "Coca", "hello"}, 16 | }, 17 | } 18 | for _, tt := range tests { 19 | t.Run(tt.name, func(t *testing.T) { 20 | if got := BuildMethodPackageInfo(tt.name); !reflect.DeepEqual(got, tt.want) { 21 | t.Errorf("BuildMethodPackageInfo() = %v, want %v", got, tt.want) 22 | } 23 | }) 24 | } 25 | } -------------------------------------------------------------------------------- /pkg/application/refactor/rename/support/refactor_change_model.go: -------------------------------------------------------------------------------- 1 | package support 2 | 3 | type RefactorChangeRelate struct { 4 | OldObj string 5 | NewObj string 6 | } 7 | 8 | type PackageClassInfo struct { 9 | Package string 10 | Class string 11 | Method string 12 | } 13 | -------------------------------------------------------------------------------- /pkg/application/refactor/rename/support/related_parser.go: -------------------------------------------------------------------------------- 1 | package support 2 | 3 | import ( 4 | "strings" 5 | ) 6 | var relates []RefactorChangeRelate 7 | 8 | func parseRelated(str string) *RefactorChangeRelate { 9 | result := &RefactorChangeRelate{"", ""} 10 | splitStr := strings.Split(str, " -> ") 11 | if len(splitStr) < 2 { 12 | return nil 13 | } 14 | 15 | result.NewObj = splitStr[1] 16 | result.OldObj = splitStr[0] 17 | return result 18 | } 19 | 20 | func ParseRelates(str string) []RefactorChangeRelate { 21 | relates = nil 22 | lines := strings.Split(str, "\n") 23 | for _, line := range lines { 24 | related := parseRelated(line) 25 | if related != nil { 26 | relates = append(relates, *related) 27 | } 28 | } 29 | 30 | return relates 31 | } 32 | -------------------------------------------------------------------------------- /pkg/application/refactor/unused/remove_unused_import_test.go: -------------------------------------------------------------------------------- 1 | package unused 2 | 3 | import ( 4 | . "github.com/onsi/gomega" 5 | "github.com/modernizing/coca/cocatest/testhelper" 6 | "path/filepath" 7 | "testing" 8 | ) 9 | 10 | func TestRemoveUnusedImportApp_Analysis(t *testing.T) { 11 | g := NewGomegaWithT(t) 12 | 13 | codePath := "../../../../_fixtures/refactor/unused" 14 | codePath = filepath.FromSlash(codePath) 15 | testhelper.ResetGitDir(codePath) 16 | 17 | deps1, _, _ := testhelper.BuildAnalysisDeps(codePath) 18 | g.Expect(len(deps1[0].Imports)).To(Equal(3)) 19 | 20 | app := NewRemoveUnusedImportApp(codePath) 21 | results := app.Analysis() 22 | 23 | g.Expect(len(results)).To(Equal(1)) 24 | 25 | errorLines := BuildErrorLines(results[0]) 26 | g.Expect(errorLines).To(Equal([]int{3, 4, 5})) 27 | 28 | app.Refactoring(results) 29 | 30 | deps, _, _ := testhelper.BuildAnalysisDeps(codePath) 31 | g.Expect(len(deps[0].Imports)).To(Equal(0)) 32 | testhelper.ResetGitDir(codePath) 33 | } 34 | -------------------------------------------------------------------------------- /pkg/application/refactor/unusedclasses/unused_classes_app.go: -------------------------------------------------------------------------------- 1 | package unusedclasses 2 | 3 | import ( 4 | "github.com/modernizing/coca/pkg/domain/core_domain" 5 | "sort" 6 | "strings" 7 | ) 8 | 9 | var analysisPackage = "" 10 | 11 | func Refactoring(parsedDeps []core_domain.CodeDataStruct) []string { 12 | sourceClasses := make(map[string]string) 13 | targetClasses := make(map[string]string) 14 | 15 | for _, node := range parsedDeps { 16 | if strings.Contains(node.Package, analysisPackage) { 17 | className := node.Package + "." + node.NodeName 18 | sourceClasses[className] = className 19 | } 20 | 21 | for _, method := range node.Functions { 22 | for _, methodCall := range method.FunctionCalls { 23 | if strings.Contains(methodCall.Package, analysisPackage) { 24 | className := methodCall.Package + "." + methodCall.NodeName 25 | targetClasses[className] = className 26 | } 27 | } 28 | } 29 | } 30 | 31 | var excludePackage []string = nil 32 | for _, clz := range sourceClasses { 33 | if targetClasses[clz] != clz { 34 | excludePackage = append(excludePackage, clz) 35 | } 36 | } 37 | 38 | sort.Strings(excludePackage) 39 | return excludePackage 40 | } 41 | -------------------------------------------------------------------------------- /pkg/application/refactor/unusedclasses/unused_classes_app_test.go: -------------------------------------------------------------------------------- 1 | package unusedclasses 2 | 3 | import ( 4 | "encoding/json" 5 | . "github.com/onsi/gomega" 6 | "github.com/modernizing/coca/cmd/cmd_util" 7 | "github.com/modernizing/coca/pkg/domain/core_domain" 8 | "path/filepath" 9 | "testing" 10 | ) 11 | 12 | func TestRefactoring(t *testing.T) { 13 | g := NewGomegaWithT(t) 14 | 15 | var parsedDeps []core_domain.CodeDataStruct 16 | codePath := "../../../../_fixtures/count/call.json" 17 | codePath = filepath.FromSlash(codePath) 18 | file := cmd_util.ReadFile(codePath) 19 | _ = json.Unmarshal(file, &parsedDeps) 20 | 21 | results := Refactoring(parsedDeps) 22 | 23 | g.Expect(len(results)).To(Equal(1)) 24 | } 25 | -------------------------------------------------------------------------------- /pkg/application/suggest/suggest_app_test.go: -------------------------------------------------------------------------------- 1 | package suggest 2 | 3 | import ( 4 | "encoding/json" 5 | "github.com/modernizing/coca/cmd/cmd_util" 6 | "github.com/modernizing/coca/pkg/domain/core_domain" 7 | "log" 8 | "path/filepath" 9 | "testing" 10 | 11 | . "github.com/onsi/gomega" 12 | ) 13 | 14 | func TestConceptAnalyser_Analysis(t *testing.T) { 15 | g := NewGomegaWithT(t) 16 | 17 | var parsedDeps []core_domain.CodeDataStruct 18 | analyser := NewSuggestApp() 19 | codePath := "../../../_fixtures/suggest/factory/factory_suggest.json" 20 | codePath = filepath.FromSlash(codePath) 21 | file := cmd_util.ReadFile(codePath) 22 | if file == nil { 23 | log.Fatal("lost file") 24 | } 25 | 26 | _ = json.Unmarshal(file, &parsedDeps) 27 | 28 | suggests := analyser.AnalysisPath(parsedDeps) 29 | 30 | g.Expect(len(suggests)).To(Equal(2)) 31 | g.Expect(suggests[0].Pattern).To(Equal("factory")) 32 | g.Expect(suggests[0].Reason).To(Equal("too many constructor")) 33 | g.Expect(suggests[1].Pattern).To(Equal("factory, builder")) 34 | g.Expect(suggests[1].Reason).To(Equal("complex constructor, too many constructor, too many parameters")) 35 | } 36 | -------------------------------------------------------------------------------- /pkg/application/todo/astitodo/README.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016 Quentin Renard 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /pkg/domain/api_domain/call_api.go: -------------------------------------------------------------------------------- 1 | package api_domain 2 | 3 | import "sort" 4 | 5 | type CallAPI struct { 6 | HTTPMethod string 7 | URI string 8 | Caller string 9 | Size int 10 | } 11 | 12 | func SortAPIs(callAPIs []CallAPI) { 13 | sort.Slice(callAPIs, func(i, j int) bool { 14 | return callAPIs[i].Size < callAPIs[j].Size 15 | }) 16 | } 17 | -------------------------------------------------------------------------------- /pkg/domain/api_domain/call_api_test.go: -------------------------------------------------------------------------------- 1 | package api_domain 2 | 3 | import ( 4 | . "github.com/onsi/gomega" 5 | "testing" 6 | ) 7 | 8 | func TestSortApi(t *testing.T) { 9 | g := NewGomegaWithT(t) 10 | var apis []CallAPI 11 | api3 := &CallAPI{"get","/blog","home", 3} 12 | api2 := &CallAPI{"get","/blog","home", 5} 13 | api5 := &CallAPI{"get","/blog","home", 2} 14 | apis = append(apis, *api3) 15 | apis = append(apis, *api2) 16 | apis = append(apis, *api5) 17 | 18 | g.Expect(apis[0].Size).To(Equal(3)) 19 | 20 | SortAPIs(apis) 21 | 22 | g.Expect(apis[0].Size).To(Equal(2)) 23 | } -------------------------------------------------------------------------------- /pkg/domain/api_domain/rest_api.go: -------------------------------------------------------------------------------- 1 | package api_domain 2 | 3 | import ( 4 | "strings" 5 | ) 6 | 7 | type RestAPI struct { 8 | Uri string 9 | HttpMethod string 10 | MethodName string 11 | ResponseStatus string 12 | RequestBodyClass string 13 | MethodParams map[string]string 14 | PackageName string 15 | ClassName string 16 | } 17 | 18 | func (r *RestAPI) BuildFullMethodPath() string { 19 | return r.PackageName + "." + r.ClassName + "." + r.MethodName 20 | } 21 | 22 | func FilterApiByPrefix(apiPrefix string, apis []RestAPI, ) []RestAPI { 23 | var restFieldsApi []RestAPI 24 | if apiPrefix != "" { 25 | for _, api := range apis { 26 | if strings.HasPrefix(api.Uri, apiPrefix) { 27 | restFieldsApi = append(restFieldsApi, api) 28 | } 29 | } 30 | } else { 31 | restFieldsApi = apis 32 | } 33 | 34 | return restFieldsApi 35 | } 36 | -------------------------------------------------------------------------------- /pkg/domain/api_domain/rest_api_test.go: -------------------------------------------------------------------------------- 1 | package api_domain 2 | 3 | import ( 4 | . "github.com/onsi/gomega" 5 | "testing" 6 | ) 7 | 8 | func Test_FilterRestApi(t *testing.T) { 9 | g := NewGomegaWithT(t) 10 | var apis []RestAPI 11 | blogApi := &RestAPI{"/blog", "", "", "", "", nil, "", "",} 12 | homeApi := &RestAPI{"/home", "", "", "", "", nil, "", "",} 13 | apis = append(apis, *blogApi) 14 | apis = append(apis, *homeApi) 15 | 16 | filteredApi := FilterApiByPrefix("/blog", apis) 17 | 18 | g.Expect(len(filteredApi)).To(Equal(1)) 19 | g.Expect(filteredApi[0].Uri).To(Equal("/blog")) 20 | } 21 | -------------------------------------------------------------------------------- /pkg/domain/bs_domain/bad_smell.go: -------------------------------------------------------------------------------- 1 | package bs_domain 2 | 3 | import "sort" 4 | 5 | type BadSmellModel struct { 6 | File string `json:"EntityName,omitempty"` 7 | Line string `json:"Line,omitempty"` 8 | Bs string `json:"BS,omitempty"` 9 | Description string `json:"Description,omitempty"` 10 | Size int `size:"Description,omitempty"` 11 | } 12 | 13 | func SortSmellByType(models []BadSmellModel, filterFunc func(key string) bool) map[string][]BadSmellModel { 14 | sortSmells := make(map[string][]BadSmellModel) 15 | for _, model := range models { 16 | sortSmells[model.Bs] = append(sortSmells[model.Bs], model) 17 | } 18 | 19 | for key, smells := range sortSmells { 20 | if filterFunc(key) { 21 | sort.Slice(smells, func(i, j int) bool { 22 | return smells[i].Size > (smells[j].Size) 23 | }) 24 | 25 | sortSmells[key] = smells 26 | } 27 | } 28 | 29 | return sortSmells 30 | } 31 | 32 | func FilterBadSmellList(models []BadSmellModel, ignoreRules map[string]bool) []BadSmellModel { 33 | var results []BadSmellModel 34 | for _, model := range models { 35 | if !ignoreRules[model.Bs] { 36 | results = append(results, model) 37 | } 38 | } 39 | return results 40 | } 41 | -------------------------------------------------------------------------------- /pkg/domain/core_domain/code_annotation.go: -------------------------------------------------------------------------------- 1 | package core_domain 2 | 3 | type AnnotationKeyValue struct { 4 | Key string 5 | Value string 6 | } 7 | 8 | func NewAnnotationKeyValue(key string, value string) AnnotationKeyValue { 9 | return AnnotationKeyValue{ 10 | Key: key, 11 | Value: value, 12 | } 13 | } 14 | 15 | type CodeAnnotation struct { 16 | Name string 17 | KeyValues []AnnotationKeyValue 18 | } 19 | 20 | func NewAnnotation() CodeAnnotation { 21 | return CodeAnnotation{ 22 | Name: "", 23 | KeyValues: nil, 24 | } 25 | } 26 | 27 | func (n *CodeAnnotation) IsComponentOrRepository() bool { 28 | return n.Name == "Component" || n.Name == "Repository" 29 | } 30 | 31 | func (n *CodeAnnotation) IsTest() bool { 32 | return n.Name == "Test" 33 | } 34 | 35 | func (n *CodeAnnotation) IsIgnoreTest() bool { 36 | return n.Name == "Ignore" 37 | } 38 | 39 | func (n *CodeAnnotation) IsIgnoreOrTest() bool { 40 | return n.IsTest() || n.IsIgnoreTest() 41 | } -------------------------------------------------------------------------------- /pkg/domain/core_domain/code_dependency.go: -------------------------------------------------------------------------------- 1 | package core_domain 2 | 3 | type CodeDependency struct { 4 | GroupId string 5 | ArtifactId string 6 | Scope string 7 | Type string 8 | Version string 9 | Optional bool 10 | } 11 | 12 | func NewCodeDependency(group string, artifact string) *CodeDependency { 13 | return &CodeDependency{ 14 | GroupId: group, 15 | ArtifactId: artifact, 16 | Optional: false, 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /pkg/domain/core_domain/code_field.go: -------------------------------------------------------------------------------- 1 | package core_domain 2 | 3 | type CodeField struct { 4 | TypeType string 5 | TypeValue string 6 | Modifiers []string 7 | } 8 | 9 | func NewJField(typeType string, typeValue string, modifier string) CodeField { 10 | property := CodeField{ 11 | TypeValue: typeValue, 12 | TypeType: typeType, 13 | } 14 | 15 | if modifier != "" { 16 | property.Modifiers = append(property.Modifiers, modifier) 17 | } 18 | 19 | return property 20 | } 21 | -------------------------------------------------------------------------------- /pkg/domain/core_domain/code_file.go: -------------------------------------------------------------------------------- 1 | package core_domain 2 | 3 | type CodeContainer struct { 4 | FullName string 5 | PackageName string 6 | Imports []CodeImport 7 | Members []CodeMember 8 | DataStructures []CodeDataStruct 9 | Fields []CodeField 10 | Containers []CodeContainer 11 | } 12 | -------------------------------------------------------------------------------- /pkg/domain/core_domain/code_import.go: -------------------------------------------------------------------------------- 1 | package core_domain 2 | 3 | type CodeImport struct { 4 | Source string 5 | AsName string 6 | ImportName string 7 | UsageName []string 8 | Scope string // function, method or class 9 | } 10 | 11 | func NewJImport(str string) CodeImport { 12 | return CodeImport{ 13 | Source: str, 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /pkg/domain/core_domain/code_member.go: -------------------------------------------------------------------------------- 1 | package core_domain 2 | 3 | type CodeMember struct { 4 | ID string 5 | AliasPackage string 6 | Name string 7 | Type string 8 | Structures []CodeDataStruct 9 | FunctionNodes []CodeFunction 10 | Namespace []string 11 | FileID string 12 | DataStructID string 13 | Position CodePosition 14 | } 15 | 16 | func NewCodeMember() *CodeMember { 17 | return &CodeMember{} 18 | } 19 | 20 | func (c *CodeMember) BuildMemberId() { 21 | IsDefaultFunction := c.DataStructID == "default" 22 | if IsDefaultFunction { 23 | for _, function := range c.FunctionNodes { 24 | c.ID = c.AliasPackage + ":" + function.Name 25 | } 26 | } else { 27 | packageName := c.FileID 28 | if c.FileID != c.AliasPackage { 29 | packageName = c.FileID + "|" + c.AliasPackage 30 | } 31 | if c.FileID == "" && c.AliasPackage != "" { 32 | packageName = c.AliasPackage 33 | } 34 | c.ID = packageName + "::" + c.DataStructID 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /pkg/domain/core_domain/code_module.go: -------------------------------------------------------------------------------- 1 | package core_domain 2 | 3 | type CodeModule struct { 4 | Packages []CodePackage 5 | PackageInfo CodePackageInfo 6 | } 7 | -------------------------------------------------------------------------------- /pkg/domain/core_domain/code_package.go: -------------------------------------------------------------------------------- 1 | package core_domain 2 | 3 | type CodePackage struct { 4 | Name string 5 | ID string 6 | CodeFiles []CodeContainer 7 | Extension interface{} 8 | } 9 | 10 | type GoCodePackage struct { 11 | Fields []CodeField 12 | } 13 | -------------------------------------------------------------------------------- /pkg/domain/core_domain/code_package_info.go: -------------------------------------------------------------------------------- 1 | package core_domain 2 | 3 | type CodePackageInfo struct { 4 | ProjectName string 5 | Dependencies []CodeDependency 6 | } 7 | -------------------------------------------------------------------------------- /pkg/domain/core_domain/code_position.go: -------------------------------------------------------------------------------- 1 | package core_domain 2 | 3 | type CodePosition struct { 4 | StartLine int 5 | StartLinePosition int 6 | StopLine int 7 | StopLinePosition int 8 | } 9 | 10 | -------------------------------------------------------------------------------- /pkg/domain/core_domain/code_project.go: -------------------------------------------------------------------------------- 1 | package core_domain 2 | 3 | type CodeProject struct { 4 | Modules []CodeModule 5 | } 6 | -------------------------------------------------------------------------------- /pkg/domain/core_domain/code_property.go: -------------------------------------------------------------------------------- 1 | package core_domain 2 | 3 | type CodeProperty struct { 4 | Modifiers []string 5 | ParamName string 6 | TypeValue string 7 | TypeType string 8 | ReturnTypes []CodeProperty 9 | Parameters []CodeProperty 10 | } 11 | 12 | func NewCodeParameter(typeType string, typeValue string) CodeProperty { 13 | return CodeProperty{ 14 | TypeValue: typeValue, 15 | TypeType: typeType, 16 | } 17 | } 18 | 19 | -------------------------------------------------------------------------------- /pkg/domain/support_domain/suggest.go: -------------------------------------------------------------------------------- 1 | package api_domain 2 | 3 | import ( 4 | "github.com/modernizing/coca/pkg/domain/core_domain" 5 | "strings" 6 | ) 7 | 8 | type Suggest struct { 9 | File string 10 | Package string 11 | Class string 12 | Pattern string 13 | Reason string 14 | Size int 15 | Line int 16 | } 17 | 18 | func NewSuggest(clz core_domain.CodeDataStruct, pattern, reason string) Suggest { 19 | return Suggest{ 20 | File: clz.FilePath, 21 | Package: clz.Package, 22 | Class: clz.NodeName, 23 | Pattern: pattern, 24 | Reason: reason, 25 | } 26 | } 27 | 28 | func MergeSuggest(clz core_domain.CodeDataStruct, currentSuggestList []Suggest) Suggest { 29 | var suggest = NewSuggest(clz, "", "") 30 | for _, s := range currentSuggestList { 31 | if !strings.Contains(suggest.Pattern, s.Pattern) { 32 | if suggest.Pattern != "" { 33 | suggest.Pattern = suggest.Pattern + ", " + s.Pattern 34 | } else { 35 | suggest.Pattern = s.Pattern 36 | } 37 | } 38 | 39 | if !strings.Contains(suggest.Reason, s.Reason) { 40 | if suggest.Reason != "" { 41 | suggest.Reason = suggest.Reason + ", " + s.Reason 42 | } else { 43 | suggest.Reason = s.Reason 44 | } 45 | } 46 | } 47 | return suggest 48 | } 49 | -------------------------------------------------------------------------------- /pkg/infrastructure/ast/ast_go/cocago_regression_test.go: -------------------------------------------------------------------------------- 1 | package ast_go 2 | 3 | func getRegressionFile(name string) string { 4 | return "testdata/regression/" + name 5 | } 6 | 7 | // todo: fix package issues with input 8 | //func Test_Regression1(t *testing.T) { 9 | // t.Parallel() 10 | // g := NewGomegaWithT(t) 11 | // 12 | // filePath := getRegressionFile("coll_stack") 13 | // results := testParser.ProcessFile(filePath + ".code") 14 | // g.Expect(cocatest.JSONFileBytesEqual(results, filePath+".json")).To(Equal(true)) 15 | //} 16 | -------------------------------------------------------------------------------- /pkg/infrastructure/ast/ast_go/parser_panic_test.go: -------------------------------------------------------------------------------- 1 | package ast_go 2 | 3 | import ( 4 | "github.com/modernizing/coca/cocatest" 5 | "path/filepath" 6 | "testing" 7 | ) 8 | 9 | func Test_ShouldPainWhenReadFileError(t *testing.T) { 10 | t.Parallel() 11 | cocatest.AssertPanic(t, errorReadFile) 12 | } 13 | 14 | func errorReadFile() { 15 | abs, _ := filepath.Abs("../../pkg/domain/code_file.go2") 16 | testParser.ProcessFile(abs) 17 | } 18 | -------------------------------------------------------------------------------- /pkg/infrastructure/ast/ast_go/testdata/method_call/local_var_method_call.code: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "sync" 6 | ) 7 | 8 | var l *sync.Mutex 9 | 10 | func main() { 11 | l = new(sync.Mutex) 12 | l.Lock() 13 | defer l.Unlock() 14 | fmt.Println("1") 15 | } 16 | -------------------------------------------------------------------------------- /pkg/infrastructure/ast/ast_go/testdata/method_call/param_method_call.code: -------------------------------------------------------------------------------- 1 | package api_domain 2 | 3 | import "sort" 4 | 5 | func SortAPIs(callAPIs []CallAPI) { 6 | sort.Slice(callAPIs, func(i, j int) bool { 7 | return callAPIs[i].Size < callAPIs[j].Size 8 | }) 9 | } 10 | -------------------------------------------------------------------------------- /pkg/infrastructure/ast/ast_go/testdata/method_call/var_inside_method_with_call.code: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "sync" 6 | ) 7 | 8 | func main() { 9 | l := new(sync.Mutex) 10 | l.Lock() 11 | defer l.Unlock() 12 | fmt.Println("1") 13 | } 14 | -------------------------------------------------------------------------------- /pkg/infrastructure/ast/ast_go/testdata/node_infos/anonymous_methods.code: -------------------------------------------------------------------------------- 1 | package testdata 2 | 3 | import "fmt" 4 | import . "time" 5 | 6 | func AnonymousMethods() { 7 | lambd := func(s string) { 8 | Sleep(10) 9 | fmt.Println(s) 10 | } 11 | 12 | lambd("From lambda!") 13 | func() { 14 | fmt.Println("Create and invoke!") 15 | }() 16 | } 17 | -------------------------------------------------------------------------------- /pkg/infrastructure/ast/ast_go/testdata/node_infos/basic_interface.code: -------------------------------------------------------------------------------- 1 | package testdata 2 | 3 | 4 | type Shape interface { 5 | Area(a float64) float64 6 | } 7 | 8 | type Object interface { 9 | Volume() float64 10 | } 11 | 12 | type Material interface { 13 | Shape 14 | Object 15 | } 16 | -------------------------------------------------------------------------------- /pkg/infrastructure/ast/ast_go/testdata/node_infos/data_struct_property.code: -------------------------------------------------------------------------------- 1 | package trial 2 | 3 | import "github.com/modernizing/coca/pkg/domain" 4 | 5 | type CodeFile struct { 6 | FullName string 7 | PackageName string 8 | Imports []string 9 | Members []CodeMember 10 | ClassNodes []domain.JClassNode 11 | } 12 | -------------------------------------------------------------------------------- /pkg/infrastructure/ast/ast_go/testdata/node_infos/hello_world.code: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | fmt.Println("hello, world") 7 | } 8 | -------------------------------------------------------------------------------- /pkg/infrastructure/ast/ast_go/testdata/node_infos/multiple_method_call.code: -------------------------------------------------------------------------------- 1 | package samples 2 | 3 | import ( 4 | "fmt" 5 | "time" 6 | ) 7 | 8 | func Ch() { 9 | var ball = make(chan string) 10 | kickBall := func(playerName string) { 11 | for { 12 | fmt.Println(<-ball, "kicked the ball.") 13 | time.Sleep(time.Second) 14 | ball <- playerName 15 | } 16 | } 17 | go kickBall("John") 18 | go kickBall("Alice") 19 | go kickBall("Bob") 20 | go kickBall("Emily") 21 | time.Sleep(time.Second * 2) 22 | ball <- "referee" // kick off 23 | 24 | var c chan bool // nil 25 | <-c // blocking here for ever 26 | } 27 | -------------------------------------------------------------------------------- /pkg/infrastructure/ast/ast_go/testdata/node_infos/nested_method.code: -------------------------------------------------------------------------------- 1 | package testdata 2 | 3 | import "fmt" 4 | 5 | func f() { 6 | foo := func(s string) { 7 | fmt.Println(s) 8 | } 9 | 10 | foo("Hello World!") 11 | } -------------------------------------------------------------------------------- /pkg/infrastructure/ast/ast_go/testdata/node_infos/normal_method.code: -------------------------------------------------------------------------------- 1 | package testdata 2 | 3 | import ( 4 | "github.com/antlr/antlr4/runtime/Go/antlr/v4" 5 | parser "github.com/modernizing/coca/languages/ts" 6 | ) 7 | 8 | func ProcessTsString(code string) *parser.TypeScriptParser { 9 | is := antlr.NewInputStream(code) 10 | return processStream(is) 11 | } 12 | 13 | func processStream(is antlr.CharStream) *parser.TypeScriptParser { 14 | lexer := parser.NewTypeScriptLexer(is) 15 | stream := antlr.NewCommonTokenStream(lexer, 0) 16 | parser := parser.NewTypeScriptParser(stream) 17 | return parser 18 | } 19 | -------------------------------------------------------------------------------- /pkg/infrastructure/ast/ast_go/testdata/node_infos/struct_type_zero.code: -------------------------------------------------------------------------------- 1 | package testdata 2 | 3 | type O struct { 4 | } 5 | 6 | func (O) typee() { 7 | 8 | } 9 | -------------------------------------------------------------------------------- /pkg/infrastructure/ast/ast_go/testdata/node_infos/struct_with_func.code: -------------------------------------------------------------------------------- 1 | package testdata 2 | 3 | type Person struct { 4 | work func() 5 | name string 6 | age int32 7 | } -------------------------------------------------------------------------------- /pkg/infrastructure/ast/ast_go/testdata/node_infos/struct_with_func_decl.code: -------------------------------------------------------------------------------- 1 | package testdata 2 | 3 | import "fmt" 4 | 5 | type person struct { 6 | name string 7 | age int 8 | personfunc func() 9 | } 10 | 11 | func (*person) outside() { 12 | fmt.Println("Declared outside and invoked!!!") 13 | } 14 | -------------------------------------------------------------------------------- /pkg/infrastructure/ast/ast_go/testdata/regression/coll_stack.code: -------------------------------------------------------------------------------- 1 | package container 2 | 3 | import ( 4 | l "container/list" 5 | "sync" 6 | ) 7 | 8 | type Stack struct { 9 | list *l.List 10 | mu sync.Mutex 11 | } 12 | 13 | func NewStack() *Stack { 14 | list := l.New() 15 | return &Stack{list: list,} 16 | } 17 | 18 | func (s *Stack) Push(t interface{}){ 19 | s.mu.Lock() 20 | defer s.mu.Unlock() 21 | s.list.PushFront(t) 22 | } 23 | 24 | func (s *Stack) Pop() interface{} { 25 | s.mu.Lock() 26 | defer s.mu.Unlock() 27 | ele := s.list.Front() 28 | if nil != ele { 29 | s.list.Remove(ele) 30 | return ele.Value 31 | } 32 | 33 | return nil 34 | } 35 | 36 | func (s *Stack) Peak() interface{} { 37 | s.mu.Lock() 38 | defer s.mu.Unlock() 39 | ele := s.list.Front() 40 | return ele.Value 41 | } 42 | 43 | func (s *Stack) Len() int { 44 | return s.list.Len() 45 | } 46 | 47 | func (s *Stack) IsEmpty() bool { 48 | return s.list.Len() == 0 49 | } 50 | -------------------------------------------------------------------------------- /pkg/infrastructure/ast/ast_groovy/gradle_process_helper.go: -------------------------------------------------------------------------------- 1 | package ast_groovy 2 | 3 | import ( 4 | "github.com/antlr/antlr4/runtime/Go/antlr/v4" 5 | "github.com/modernizing/coca/languages/groovy" 6 | ) 7 | 8 | func ProcessGroovyString(code string) *parser.GroovyParser { 9 | is := antlr.NewInputStream(code) 10 | lexer := parser.NewGroovyLexer(is) 11 | stream := antlr.NewCommonTokenStream(lexer, 0) 12 | parser := parser.NewGroovyParser(stream) 13 | return parser 14 | } 15 | -------------------------------------------------------------------------------- /pkg/infrastructure/ast/ast_java/java_full_listener_test.go: -------------------------------------------------------------------------------- 1 | package ast_java 2 | -------------------------------------------------------------------------------- /pkg/infrastructure/ast/ast_java/java_process_helper.go: -------------------------------------------------------------------------------- 1 | package ast_java 2 | 3 | import ( 4 | "github.com/antlr/antlr4/runtime/Go/antlr/v4" 5 | "github.com/modernizing/coca/languages/java" 6 | ) 7 | 8 | func ProcessJavaFile(path string) *parser.JavaParser { 9 | is, _ := antlr.NewFileStream(path) 10 | return processStream(is) 11 | } 12 | 13 | func processStream(is antlr.CharStream) *parser.JavaParser { 14 | lexer := parser.NewJavaLexer(is) 15 | stream := antlr.NewCommonTokenStream(lexer, 0) 16 | parser := parser.NewJavaParser(stream) 17 | return parser 18 | } 19 | 20 | func ProcessJavaString(code string) *parser.JavaParser { 21 | is := antlr.NewInputStream(code) 22 | return processStream(is) 23 | } 24 | -------------------------------------------------------------------------------- /pkg/infrastructure/ast/astutil/pare_tree_util.go: -------------------------------------------------------------------------------- 1 | package astutil 2 | 3 | import "github.com/antlr/antlr4/runtime/Go/antlr/v4" 4 | 5 | func GetNodeIndex(node antlr.ParseTree) int { 6 | if node == nil || node.GetParent() == nil { 7 | return -1 8 | } 9 | parent := node.GetParent() 10 | 11 | for i := 0; i < parent.GetChildCount(); i++ { 12 | if parent.GetChild(i) == node { 13 | return i 14 | } 15 | } 16 | return 0 17 | } 18 | -------------------------------------------------------------------------------- /pkg/infrastructure/ast/astutil/position.go: -------------------------------------------------------------------------------- 1 | package astutil 2 | 3 | import ( 4 | "github.com/antlr/antlr4/runtime/Go/antlr/v4" 5 | "github.com/modernizing/coca/pkg/domain/core_domain" 6 | ) 7 | 8 | func AddFunctionPosition(m *core_domain.CodeFunction, ctx *antlr.BaseParserRuleContext) { 9 | m.Position.StartLine = ctx.GetStart().GetLine() 10 | m.Position.StartLinePosition = ctx.GetStart().GetColumn() 11 | m.Position.StopLine = ctx.GetStop().GetLine() 12 | m.Position.StopLinePosition = ctx.GetStop().GetColumn() 13 | } 14 | -------------------------------------------------------------------------------- /pkg/infrastructure/container/coll_stack.go: -------------------------------------------------------------------------------- 1 | package container 2 | 3 | import ( 4 | l "container/list" 5 | "sync" 6 | ) 7 | 8 | type Stack struct { 9 | list *l.List 10 | mu sync.Mutex 11 | } 12 | 13 | func NewStack() *Stack { 14 | list := l.New() 15 | return &Stack{list: list,} 16 | } 17 | 18 | func (s *Stack) Push(t interface{}){ 19 | s.mu.Lock() 20 | defer s.mu.Unlock() 21 | s.list.PushFront(t) 22 | } 23 | 24 | func (s *Stack) Pop() interface{} { 25 | s.mu.Lock() 26 | defer s.mu.Unlock() 27 | ele := s.list.Front() 28 | if nil != ele { 29 | s.list.Remove(ele) 30 | return ele.Value 31 | } 32 | 33 | return nil 34 | } 35 | 36 | func (s *Stack) Peak() interface{} { 37 | s.mu.Lock() 38 | defer s.mu.Unlock() 39 | ele := s.list.Front() 40 | return ele.Value 41 | } 42 | 43 | func (s *Stack) Len() int { 44 | return s.list.Len() 45 | } 46 | 47 | func (s *Stack) IsEmpty() bool { 48 | return s.list.Len() == 0 49 | } 50 | -------------------------------------------------------------------------------- /pkg/infrastructure/jpackage/jpackage.go: -------------------------------------------------------------------------------- 1 | package jpackage 2 | 3 | import "strings" 4 | 5 | func GetClassName(path string) string { 6 | split := strings.Split(path, ".") 7 | return strings.Join(split[:len(split)-1], ".") 8 | } 9 | 10 | func GetMethodName(path string) string { 11 | split := strings.Split(path, ".") 12 | return strings.Join(split[len(split)-1:], ".") 13 | } 14 | 15 | -------------------------------------------------------------------------------- /pkg/infrastructure/jpackage/jpackage_test.go: -------------------------------------------------------------------------------- 1 | package jpackage 2 | 3 | import "testing" 4 | 5 | func TestGetMethodName(t *testing.T) { 6 | tests := []struct { 7 | name string 8 | origin string 9 | want string 10 | }{ 11 | {"get package", "com.phodal.coca.JPackage.getMethodName", "getMethodName"}, 12 | } 13 | for _, tt := range tests { 14 | t.Run(tt.name, func(t *testing.T) { 15 | if got := GetMethodName(tt.origin); got != tt.want { 16 | t.Errorf("GetMethodName() = %v, want %v", got, tt.want) 17 | } 18 | }) 19 | } 20 | } 21 | 22 | func TestGetClassName(t *testing.T) { 23 | tests := []struct { 24 | name string 25 | path string 26 | want string 27 | }{ 28 | {"get package", "JPackage.getMethodName", "JPackage"}, 29 | } 30 | for _, tt := range tests { 31 | t.Run(tt.name, func(t *testing.T) { 32 | if got := GetClassName(tt.path); got != tt.want { 33 | t.Errorf("GetClassName() = %v, want %v", got, tt.want) 34 | } 35 | }) 36 | } 37 | } -------------------------------------------------------------------------------- /pkg/infrastructure/string_helper/coca_sort.go: -------------------------------------------------------------------------------- 1 | package string_helper 2 | 3 | import ( 4 | "github.com/yourbasic/radix" 5 | ) 6 | 7 | // from: https://stackoverflow.com/questions/18695346/how-to-sort-a-mapstringint-by-its-values 8 | func SortWord(wordFrequencies map[string]int) PairList { 9 | pl := make(PairList, len(wordFrequencies)) 10 | i := 0 11 | for k, v := range wordFrequencies { 12 | pl[i] = Pair{k, v} 13 | i++ 14 | } 15 | 16 | radix.SortSlice(pl, func(i int) string { return pl[i].Key }) 17 | return pl 18 | } 19 | 20 | type Pair struct { 21 | Key string 22 | Value int 23 | } 24 | 25 | type PairList []Pair 26 | 27 | func (p PairList) Len() int { return len(p) } 28 | func (p PairList) Less(i, j int) bool { return p[i].Value < p[j].Value } 29 | func (p PairList) Swap(i, j int) { p[i], p[j] = p[j], p[i] } 30 | -------------------------------------------------------------------------------- /pkg/infrastructure/string_helper/string_array.go: -------------------------------------------------------------------------------- 1 | package string_helper 2 | 3 | import "sort" 4 | 5 | func StringArrayContains(s []string, searchterm string) bool { 6 | i := sort.SearchStrings(s, searchterm) 7 | return i < len(s) && s[i] == searchterm 8 | } 9 | -------------------------------------------------------------------------------- /pkg/infrastructure/xmlparse/README.md: -------------------------------------------------------------------------------- 1 | Based On: https://github.com/wenj91/gobatis 2 | 3 | -------------------------------------------------------------------------------- /scripts/build.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | GOOS=windows GOARCH=amd64 go build coca.go 4 | -------------------------------------------------------------------------------- /scripts/compile-antlr.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | cd languages/java 4 | 5 | antlr -Dlanguage=Go -listener JavaLexer.g4 6 | antlr -Dlanguage=Go -listener JavaParser.g4 7 | 8 | cd ../g4 9 | 10 | antlr -Dlanguage=Go -listener GroovyLexer.g4 -o ../groovy 11 | antlr -Dlanguage=Go -listener GroovyParser.g4 -o ../groovy 12 | 13 | antlr -Dlanguage=Go -listener JavaScriptLexer.g4 -o ../js 14 | antlr -Dlanguage=Go -listener JavaScriptParser.g4 -o ../js 15 | 16 | 17 | #antlr -Dlanguage=Go -listener GoLexer.g4 -o ../go 18 | #antlr -Dlanguage=Go -listener GoParser.g4 -o ../go 19 | 20 | antlr -Dlanguage=Go -listener PythonLexer.g4 -o ../python 21 | antlr -Dlanguage=Go -listener PythonParser.g4 -o ../python 22 | 23 | #antlr -Dlanguage=Java -listener PythonLexer.g4 -o ../compare/java 24 | #antlr -Dlanguage=Java -listener PythonParser.g4 -o ../compare/java 25 | 26 | #antlr -Dlanguage=Java -listener TypeScriptLexer.g4 -o ../compare/src/main/java/tsantlr 27 | #antlr -Dlanguage=Java -listener TypeScriptParser.g4 -o ../compare/src/main/java/tsantlr 28 | 29 | antlr -Dlanguage=Go -listener CommentLexer.g4 -o ../comment 30 | -------------------------------------------------------------------------------- /scripts/go.test.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e 4 | echo "" > coverage.txt 5 | 6 | for d in $(go list ./... | grep -v vendor); do 7 | go test -race -coverprofile=profile.out -covermode=atomic "$d" 8 | if [ -f profile.out ]; then 9 | cat profile.out >> coverage.txt 10 | rm profile.out 11 | fi 12 | done --------------------------------------------------------------------------------