From 1effdf25316aca0758babce13f917c853722dda9 Mon Sep 17 00:00:00 2001 From: Gang ZHANG Date: Mon, 14 Jan 2019 13:38:48 +0800 Subject: [PATCH] can parse ruby import relations --- .gitignore | 1 + .../java/depends/DependsCommand.java | 76 + data/undertestsrc/java/depends/Main.java | 84 + .../depends/addons/DV8MappingFileBuilder.java | 79 + .../java/depends/deptypes/DependencyType.java | 39 + .../java/depends/entity/AnonymousBlock.java | 9 + .../java/depends/entity/ContainerEntity.java | 235 ++ .../java/depends/entity/EmptyTypeEntity.java | 9 + .../java/depends/entity/Entity.java | 152 ++ .../java/depends/entity/Expression.java | 107 + .../java/depends/entity/FileEntity.java | 89 + .../java/depends/entity/FunctionEntity.java | 78 + .../depends/entity/MultiDeclareEntities.java | 55 + .../java/depends/entity/PackageEntity.java | 12 + .../java/depends/entity/TypeAliasEntity.java | 43 + .../java/depends/entity/TypeEntity.java | 72 + .../java/depends/entity/VarEntity.java | 37 + .../java/depends/entity/repo/BuiltInType.java | 38 + .../entity/repo/EntityNotExistsException.java | 11 + .../java/depends/entity/repo/EntityRepo.java | 54 + .../java/depends/entity/repo/IdGenerator.java | 15 + ...equestedTypeOfAncestorExistsException.java | 12 + .../depends/entity/repo/NullBuiltInType.java | 15 + .../depends/extractor/AbstractLangWorker.java | 114 + .../java/depends/extractor/FileParser.java | 8 + .../depends/extractor/HandlerContext.java | 178 ++ .../java/depends/extractor/LangWorkers.java | 18 + .../depends/extractor/cpp/CppBuiltInType.java | 47 + .../depends/extractor/cpp/CppFileParser.java | 14 + .../cpp/CppImportLookupStrategy.java | 87 + .../java/depends/extractor/cpp/CppWorker.java | 43 + ...ParserExtensionConfigurationExtension.java | 22 + .../extractor/cpp/cdt/ASTStringUtil.java | 1222 +++++++++ .../depends/extractor/cpp/cdt/CDTParser.java | 71 + .../cpp/cdt/CdtCppEntitiesListener.java | 276 ++ .../extractor/cpp/cdt/CdtCppFileParser.java | 50 + .../extractor/cpp/cdt/CommentManager.java | 61 + .../extractor/cpp/cdt/CppHandlerContext.java | 20 + .../extractor/cpp/cdt/ExpressionUsage.java | 190 ++ ...ParserExtensionConfigurationExtension.java | 22 + .../extractor/cpp/cdt/MacroExtractor.java | 31 + .../cpp/cdt/PreprocessorHandler.java | 49 + .../extractor/java/JavaBuiltInType.java | 64 + .../extractor/java/JavaEntitiesListener.java | 325 +++ .../extractor/java/JavaFileParser.java | 36 + .../extractor/java/JavaHandlerContext.java | 23 + .../java/JavaImportLookupStrategy.java | 54 + .../depends/extractor/java/JavaWorker.java | 40 + .../java/context/AnnotationProcessor.java | 70 + .../java/context/ClassTypeContextHelper.java | 39 + .../java/context/CreatorContextHelper.java | 16 + .../java/context/ExpressionUsage.java | 182 ++ .../FormalParameterListContextHelper.java | 74 + .../java/context/IdentifierContextHelper.java | 16 + .../extractor/java/context/OpHelper.java | 37 + .../context/QualitiedNameContextHelper.java | 28 + .../context/TypeParameterContextHelper.java | 19 + .../VariableDeclaratorsContextHelper.java | 40 + .../extractor/ruby/RubyBuiltInType.java | 23 + .../extractor/ruby/RubyFileParser.java | 35 + .../ruby/RubyImportLookupStrategy.java | 38 + .../depends/extractor/ruby/RubyListener.java | 9 + .../depends/extractor/ruby/RubyWorker.java | 41 + .../AbstractFormatDependencyDumper.java | 23 + .../java/depends/format/DependencyDumper.java | 49 + .../java/depends/format/FileAttributes.java | 18 + .../DetailTextFormatDependencyDumper.java | 48 + .../format/dot/DotFormatDependencyDumper.java | 52 + .../excel/ExcelFormatDependencyDumper.java | 96 + .../java/depends/format/json/JCellObject.java | 41 + .../depends/format/json/JDataBuilder.java | 49 + .../java/depends/format/json/JDepObject.java | 50 + .../json/JsonFormatDependencyDumper.java | 41 + .../format/path/DotPathFilenameWritter.java | 26 + .../format/path/EmptyFilenameWritter.java | 10 + .../java/depends/format/xml/XCell.java | 38 + .../java/depends/format/xml/XCells.java | 17 + .../java/depends/format/xml/XDataBuilder.java | 58 + .../java/depends/format/xml/XDepObject.java | 65 + .../java/depends/format/xml/XDepend.java | 30 + .../java/depends/format/xml/XFiles.java | 18 + .../format/xml/XmlFormatDependencyDumper.java | 39 + .../depends/importtypes/ExactMatchImport.java | 7 + .../java/depends/importtypes/FileImport.java | 7 + .../java/depends/importtypes/Import.java | 11 + .../importtypes/PackageWildCardImport.java | 7 + .../depends/matrix/DependencyGenerator.java | 7 + .../java/depends/matrix/DependencyMatrix.java | 86 + .../java/depends/matrix/DependencyPair.java | 39 + .../java/depends/matrix/DependencyValue.java | 33 + .../matrix/FileDependencyGenerator.java | 45 + .../java/depends/matrix/FilenameWritter.java | 5 + .../matrix/FunctionDependencyGenerator.java | 50 + .../relations/ImportLookupStrategy.java | 15 + .../java/depends/relations/Inferer.java | 258 ++ .../java/depends/relations/Relation.java | 28 + .../depends/relations/RelationCounter.java | 118 + .../java/depends/util/FileTraversal.java | 68 + .../java/depends/util/FileUtil.java | 19 + .../depends/extractor/java/JavaLexer.g4 | 1 - .../depends/extractor/ruby/RubyLexer.g4 | 472 ---- .../depends/extractor/ruby/RubyParser.g4 | 300 --- .../depends/extractor/ruby/compiletest.sh | 11 - .../antlr4/depends/extractor/ruby/debug.sh | 3 - .../antlr4/depends/extractor/ruby/test.sh | 3 - .../depends/extractor/ruby/test/BEGIN_END.rb | 12 - .../depends/extractor/ruby/test/ambgious1.rb | 4 - .../depends/extractor/ruby/test/ambgious2.rb | 4 - .../depends/extractor/ruby/test/array_ref.rb | 2 - .../depends/extractor/ruby/test/assign.rb | 1 - .../depends/extractor/ruby/test/assign1.rb | 1 - .../extractor/ruby/test/attr_accessor.rb | 9 - .../depends/extractor/ruby/test/block.rb | 13 - .../depends/extractor/ruby/test/case.rb | 2 - .../depends/extractor/ruby/test/class.rb | 34 - .../depends/extractor/ruby/test/class2.rb | 4 - .../extractor/ruby/test/comment-in-block.rb | 9 - ...omment-singleline-with-additional-terms.rb | 11 - .../extractor/ruby/test/comment-singleline.rb | 3 - .../extractor/ruby/test/comment_in_middle.rb | 3 - .../depends/extractor/ruby/test/dis_regex.rb | 1 - .../depends/extractor/ruby/test/dotref.rb | 1 - .../depends/extractor/ruby/test/expression.rb | 28 - .../depends/extractor/ruby/test/func.rb | 43 - .../depends/extractor/ruby/test/func1.rb | 18 - .../depends/extractor/ruby/test/func2.rb | 1 - .../depends/extractor/ruby/test/func3.rb | 12 - .../depends/extractor/ruby/test/func_call.rb | 10 - .../depends/extractor/ruby/test/func_call2.rb | 1 - .../depends/extractor/ruby/test/func_param.rb | 3 - .../extractor/ruby/test/function_name.rb | 7 - .../extractor/ruby/test/global_varref.rb | 1 - .../depends/extractor/ruby/test/hash.rb | 22 - .../depends/extractor/ruby/test/helloworld.rb | 3 - .../depends/extractor/ruby/test/heredoc.rb | 16 - .../depends/extractor/ruby/test/heredoc1.rb | 24 - .../depends/extractor/ruby/test/heredoc2.rb | 8 - .../extractor/ruby/test/infinite_loop_err.rb | 14 - .../depends/extractor/ruby/test/literals.rb | 51 - .../depends/extractor/ruby/test/loop.rb | 2 - .../extractor/ruby/test/loop_statement.rb | 53 - .../depends/extractor/ruby/test/minitest.rb | 857 ------ .../depends/extractor/ruby/test/moduletest.rb | 13 - .../depends/extractor/ruby/test/newinvoke.rb | 1 - .../depends/extractor/ruby/test/next.rb | 9 - .../extractor/ruby/test/quoted_string.rb | 7 - .../ruby/test/quoted_string_example.rb | 9 - .../depends/extractor/ruby/test/range.rb | 8 - .../depends/extractor/ruby/test/regex2.rb | 3 - .../depends/extractor/ruby/test/regex3.rb | 1 - .../depends/extractor/ruby/test/require.rb | 1 - .../extractor/ruby/test/rescure_retry.rb | 35 - .../extractor/ruby/test/single_char_string.rb | 34 - .../extractor/ruby/test/special_func_name.rb | 11 - .../depends/extractor/ruby/test/string.rb | 2 - .../antlr4/depends/extractor/ruby/test/t.rb | 25 - .../antlr4/depends/extractor/ruby/test/t1.rb | 16 - .../antlr4/depends/extractor/ruby/test/t10.rb | 9 - .../antlr4/depends/extractor/ruby/test/t11.rb | 1 - .../antlr4/depends/extractor/ruby/test/t12.rb | 6 - .../antlr4/depends/extractor/ruby/test/t3.rb | 16 - .../antlr4/depends/extractor/ruby/test/t4.rb | 38 - .../antlr4/depends/extractor/ruby/test/t6.rb | 10 - .../antlr4/depends/extractor/ruby/test/t8.rb | 1 - .../antlr4/depends/extractor/ruby/test/t9.rb | 5 - .../depends/extractor/ruby/test/test.rb | 2367 ----------------- .../depends/extractor/ruby/test/throwcatch.rb | 15 - .../depends/extractor/ruby/test/truncked.rb | 11 - .../depends/extractor/ruby/test/unless.rb | 6 - .../depends/extractor/ruby/test/when.rb | 6 - .../extractor/ruby/test/when_statement.rb | 13 - .../antlr4/depends/extractor/ruby/test_all.sh | 4 - .../extractor/ruby/test_all_in_computer.sh | 5 - .../depends/extractor/ruby/tokentest.sh | 11 - .../antlr4/depends/extractor/ruby/tree.sh | 3 - .../java/depends/entity/ContainerEntity.java | 25 +- src/main/java/depends/entity/VarEntity.java | 6 +- .../depends/extractor/HandlerContext.java | 5 + .../cpp/cdt/CdtCppEntitiesListener.java | 3 - .../extractor/ruby/IncludedFileLocator.java | 24 + .../extractor/ruby/RubyFileParser.java | 17 +- .../extractor/ruby/RubyHandlerContext.java | 64 + .../ruby/RubyImportLookupStrategy.java | 22 +- .../depends/extractor/ruby/RubyListener.java | 166 +- .../extractor/ruby/RubyParserHelper.java | 145 + .../depends/extractor/ruby/RubyWorker.java | 11 +- src/main/java/depends/util/FileUtil.java | 6 + .../extractor/ruby/RubyParserTest.java | 28 + .../extractor/ruby/RubyRequireTest.java | 31 + .../resources/ruby-code-examples/require_1.rb | 1 + .../resources/ruby-code-examples/require_2.rb | 1 + 191 files changed, 7150 insertions(+), 4810 deletions(-) create mode 100644 data/undertestsrc/java/depends/DependsCommand.java create mode 100644 data/undertestsrc/java/depends/Main.java create mode 100644 data/undertestsrc/java/depends/addons/DV8MappingFileBuilder.java create mode 100644 data/undertestsrc/java/depends/deptypes/DependencyType.java create mode 100644 data/undertestsrc/java/depends/entity/AnonymousBlock.java create mode 100644 data/undertestsrc/java/depends/entity/ContainerEntity.java create mode 100644 data/undertestsrc/java/depends/entity/EmptyTypeEntity.java create mode 100644 data/undertestsrc/java/depends/entity/Entity.java create mode 100644 data/undertestsrc/java/depends/entity/Expression.java create mode 100644 data/undertestsrc/java/depends/entity/FileEntity.java create mode 100644 data/undertestsrc/java/depends/entity/FunctionEntity.java create mode 100644 data/undertestsrc/java/depends/entity/MultiDeclareEntities.java create mode 100644 data/undertestsrc/java/depends/entity/PackageEntity.java create mode 100644 data/undertestsrc/java/depends/entity/TypeAliasEntity.java create mode 100644 data/undertestsrc/java/depends/entity/TypeEntity.java create mode 100644 data/undertestsrc/java/depends/entity/VarEntity.java create mode 100644 data/undertestsrc/java/depends/entity/repo/BuiltInType.java create mode 100644 data/undertestsrc/java/depends/entity/repo/EntityNotExistsException.java create mode 100644 data/undertestsrc/java/depends/entity/repo/EntityRepo.java create mode 100644 data/undertestsrc/java/depends/entity/repo/IdGenerator.java create mode 100644 data/undertestsrc/java/depends/entity/repo/NoRequestedTypeOfAncestorExistsException.java create mode 100644 data/undertestsrc/java/depends/entity/repo/NullBuiltInType.java create mode 100644 data/undertestsrc/java/depends/extractor/AbstractLangWorker.java create mode 100644 data/undertestsrc/java/depends/extractor/FileParser.java create mode 100644 data/undertestsrc/java/depends/extractor/HandlerContext.java create mode 100644 data/undertestsrc/java/depends/extractor/LangWorkers.java create mode 100644 data/undertestsrc/java/depends/extractor/cpp/CppBuiltInType.java create mode 100644 data/undertestsrc/java/depends/extractor/cpp/CppFileParser.java create mode 100644 data/undertestsrc/java/depends/extractor/cpp/CppImportLookupStrategy.java create mode 100644 data/undertestsrc/java/depends/extractor/cpp/CppWorker.java create mode 100644 data/undertestsrc/java/depends/extractor/cpp/cdt/ANSICParserExtensionConfigurationExtension.java create mode 100644 data/undertestsrc/java/depends/extractor/cpp/cdt/ASTStringUtil.java create mode 100644 data/undertestsrc/java/depends/extractor/cpp/cdt/CDTParser.java create mode 100644 data/undertestsrc/java/depends/extractor/cpp/cdt/CdtCppEntitiesListener.java create mode 100644 data/undertestsrc/java/depends/extractor/cpp/cdt/CdtCppFileParser.java create mode 100644 data/undertestsrc/java/depends/extractor/cpp/cdt/CommentManager.java create mode 100644 data/undertestsrc/java/depends/extractor/cpp/cdt/CppHandlerContext.java create mode 100644 data/undertestsrc/java/depends/extractor/cpp/cdt/ExpressionUsage.java create mode 100644 data/undertestsrc/java/depends/extractor/cpp/cdt/GPPParserExtensionConfigurationExtension.java create mode 100644 data/undertestsrc/java/depends/extractor/cpp/cdt/MacroExtractor.java create mode 100644 data/undertestsrc/java/depends/extractor/cpp/cdt/PreprocessorHandler.java create mode 100644 data/undertestsrc/java/depends/extractor/java/JavaBuiltInType.java create mode 100644 data/undertestsrc/java/depends/extractor/java/JavaEntitiesListener.java create mode 100644 data/undertestsrc/java/depends/extractor/java/JavaFileParser.java create mode 100644 data/undertestsrc/java/depends/extractor/java/JavaHandlerContext.java create mode 100644 data/undertestsrc/java/depends/extractor/java/JavaImportLookupStrategy.java create mode 100644 data/undertestsrc/java/depends/extractor/java/JavaWorker.java create mode 100644 data/undertestsrc/java/depends/extractor/java/context/AnnotationProcessor.java create mode 100644 data/undertestsrc/java/depends/extractor/java/context/ClassTypeContextHelper.java create mode 100644 data/undertestsrc/java/depends/extractor/java/context/CreatorContextHelper.java create mode 100644 data/undertestsrc/java/depends/extractor/java/context/ExpressionUsage.java create mode 100644 data/undertestsrc/java/depends/extractor/java/context/FormalParameterListContextHelper.java create mode 100644 data/undertestsrc/java/depends/extractor/java/context/IdentifierContextHelper.java create mode 100644 data/undertestsrc/java/depends/extractor/java/context/OpHelper.java create mode 100644 data/undertestsrc/java/depends/extractor/java/context/QualitiedNameContextHelper.java create mode 100644 data/undertestsrc/java/depends/extractor/java/context/TypeParameterContextHelper.java create mode 100644 data/undertestsrc/java/depends/extractor/java/context/VariableDeclaratorsContextHelper.java create mode 100644 data/undertestsrc/java/depends/extractor/ruby/RubyBuiltInType.java create mode 100644 data/undertestsrc/java/depends/extractor/ruby/RubyFileParser.java create mode 100644 data/undertestsrc/java/depends/extractor/ruby/RubyImportLookupStrategy.java create mode 100644 data/undertestsrc/java/depends/extractor/ruby/RubyListener.java create mode 100644 data/undertestsrc/java/depends/extractor/ruby/RubyWorker.java create mode 100644 data/undertestsrc/java/depends/format/AbstractFormatDependencyDumper.java create mode 100644 data/undertestsrc/java/depends/format/DependencyDumper.java create mode 100644 data/undertestsrc/java/depends/format/FileAttributes.java create mode 100644 data/undertestsrc/java/depends/format/detail/DetailTextFormatDependencyDumper.java create mode 100644 data/undertestsrc/java/depends/format/dot/DotFormatDependencyDumper.java create mode 100644 data/undertestsrc/java/depends/format/excel/ExcelFormatDependencyDumper.java create mode 100644 data/undertestsrc/java/depends/format/json/JCellObject.java create mode 100644 data/undertestsrc/java/depends/format/json/JDataBuilder.java create mode 100644 data/undertestsrc/java/depends/format/json/JDepObject.java create mode 100644 data/undertestsrc/java/depends/format/json/JsonFormatDependencyDumper.java create mode 100644 data/undertestsrc/java/depends/format/path/DotPathFilenameWritter.java create mode 100644 data/undertestsrc/java/depends/format/path/EmptyFilenameWritter.java create mode 100644 data/undertestsrc/java/depends/format/xml/XCell.java create mode 100644 data/undertestsrc/java/depends/format/xml/XCells.java create mode 100644 data/undertestsrc/java/depends/format/xml/XDataBuilder.java create mode 100644 data/undertestsrc/java/depends/format/xml/XDepObject.java create mode 100644 data/undertestsrc/java/depends/format/xml/XDepend.java create mode 100644 data/undertestsrc/java/depends/format/xml/XFiles.java create mode 100644 data/undertestsrc/java/depends/format/xml/XmlFormatDependencyDumper.java create mode 100644 data/undertestsrc/java/depends/importtypes/ExactMatchImport.java create mode 100644 data/undertestsrc/java/depends/importtypes/FileImport.java create mode 100644 data/undertestsrc/java/depends/importtypes/Import.java create mode 100644 data/undertestsrc/java/depends/importtypes/PackageWildCardImport.java create mode 100644 data/undertestsrc/java/depends/matrix/DependencyGenerator.java create mode 100644 data/undertestsrc/java/depends/matrix/DependencyMatrix.java create mode 100644 data/undertestsrc/java/depends/matrix/DependencyPair.java create mode 100644 data/undertestsrc/java/depends/matrix/DependencyValue.java create mode 100644 data/undertestsrc/java/depends/matrix/FileDependencyGenerator.java create mode 100644 data/undertestsrc/java/depends/matrix/FilenameWritter.java create mode 100644 data/undertestsrc/java/depends/matrix/FunctionDependencyGenerator.java create mode 100644 data/undertestsrc/java/depends/relations/ImportLookupStrategy.java create mode 100644 data/undertestsrc/java/depends/relations/Inferer.java create mode 100644 data/undertestsrc/java/depends/relations/Relation.java create mode 100644 data/undertestsrc/java/depends/relations/RelationCounter.java create mode 100644 data/undertestsrc/java/depends/util/FileTraversal.java create mode 100644 data/undertestsrc/java/depends/util/FileUtil.java delete mode 100644 src/main/antlr4/depends/extractor/ruby/RubyLexer.g4 delete mode 100644 src/main/antlr4/depends/extractor/ruby/RubyParser.g4 delete mode 100755 src/main/antlr4/depends/extractor/ruby/compiletest.sh delete mode 100755 src/main/antlr4/depends/extractor/ruby/debug.sh delete mode 100755 src/main/antlr4/depends/extractor/ruby/test.sh delete mode 100644 src/main/antlr4/depends/extractor/ruby/test/BEGIN_END.rb delete mode 100644 src/main/antlr4/depends/extractor/ruby/test/ambgious1.rb delete mode 100644 src/main/antlr4/depends/extractor/ruby/test/ambgious2.rb delete mode 100644 src/main/antlr4/depends/extractor/ruby/test/array_ref.rb delete mode 100644 src/main/antlr4/depends/extractor/ruby/test/assign.rb delete mode 100644 src/main/antlr4/depends/extractor/ruby/test/assign1.rb delete mode 100644 src/main/antlr4/depends/extractor/ruby/test/attr_accessor.rb delete mode 100644 src/main/antlr4/depends/extractor/ruby/test/block.rb delete mode 100644 src/main/antlr4/depends/extractor/ruby/test/case.rb delete mode 100644 src/main/antlr4/depends/extractor/ruby/test/class.rb delete mode 100644 src/main/antlr4/depends/extractor/ruby/test/class2.rb delete mode 100644 src/main/antlr4/depends/extractor/ruby/test/comment-in-block.rb delete mode 100644 src/main/antlr4/depends/extractor/ruby/test/comment-singleline-with-additional-terms.rb delete mode 100644 src/main/antlr4/depends/extractor/ruby/test/comment-singleline.rb delete mode 100644 src/main/antlr4/depends/extractor/ruby/test/comment_in_middle.rb delete mode 100644 src/main/antlr4/depends/extractor/ruby/test/dis_regex.rb delete mode 100644 src/main/antlr4/depends/extractor/ruby/test/dotref.rb delete mode 100644 src/main/antlr4/depends/extractor/ruby/test/expression.rb delete mode 100644 src/main/antlr4/depends/extractor/ruby/test/func.rb delete mode 100644 src/main/antlr4/depends/extractor/ruby/test/func1.rb delete mode 100644 src/main/antlr4/depends/extractor/ruby/test/func2.rb delete mode 100755 src/main/antlr4/depends/extractor/ruby/test/func3.rb delete mode 100644 src/main/antlr4/depends/extractor/ruby/test/func_call.rb delete mode 100644 src/main/antlr4/depends/extractor/ruby/test/func_call2.rb delete mode 100644 src/main/antlr4/depends/extractor/ruby/test/func_param.rb delete mode 100644 src/main/antlr4/depends/extractor/ruby/test/function_name.rb delete mode 100644 src/main/antlr4/depends/extractor/ruby/test/global_varref.rb delete mode 100644 src/main/antlr4/depends/extractor/ruby/test/hash.rb delete mode 100644 src/main/antlr4/depends/extractor/ruby/test/helloworld.rb delete mode 100644 src/main/antlr4/depends/extractor/ruby/test/heredoc.rb delete mode 100644 src/main/antlr4/depends/extractor/ruby/test/heredoc1.rb delete mode 100644 src/main/antlr4/depends/extractor/ruby/test/heredoc2.rb delete mode 100644 src/main/antlr4/depends/extractor/ruby/test/infinite_loop_err.rb delete mode 100644 src/main/antlr4/depends/extractor/ruby/test/literals.rb delete mode 100644 src/main/antlr4/depends/extractor/ruby/test/loop.rb delete mode 100644 src/main/antlr4/depends/extractor/ruby/test/loop_statement.rb delete mode 100644 src/main/antlr4/depends/extractor/ruby/test/minitest.rb delete mode 100644 src/main/antlr4/depends/extractor/ruby/test/moduletest.rb delete mode 100644 src/main/antlr4/depends/extractor/ruby/test/newinvoke.rb delete mode 100644 src/main/antlr4/depends/extractor/ruby/test/next.rb delete mode 100644 src/main/antlr4/depends/extractor/ruby/test/quoted_string.rb delete mode 100755 src/main/antlr4/depends/extractor/ruby/test/quoted_string_example.rb delete mode 100644 src/main/antlr4/depends/extractor/ruby/test/range.rb delete mode 100644 src/main/antlr4/depends/extractor/ruby/test/regex2.rb delete mode 100644 src/main/antlr4/depends/extractor/ruby/test/regex3.rb delete mode 100644 src/main/antlr4/depends/extractor/ruby/test/require.rb delete mode 100644 src/main/antlr4/depends/extractor/ruby/test/rescure_retry.rb delete mode 100644 src/main/antlr4/depends/extractor/ruby/test/single_char_string.rb delete mode 100644 src/main/antlr4/depends/extractor/ruby/test/special_func_name.rb delete mode 100644 src/main/antlr4/depends/extractor/ruby/test/string.rb delete mode 100644 src/main/antlr4/depends/extractor/ruby/test/t.rb delete mode 100644 src/main/antlr4/depends/extractor/ruby/test/t1.rb delete mode 100644 src/main/antlr4/depends/extractor/ruby/test/t10.rb delete mode 100644 src/main/antlr4/depends/extractor/ruby/test/t11.rb delete mode 100644 src/main/antlr4/depends/extractor/ruby/test/t12.rb delete mode 100644 src/main/antlr4/depends/extractor/ruby/test/t3.rb delete mode 100644 src/main/antlr4/depends/extractor/ruby/test/t4.rb delete mode 100644 src/main/antlr4/depends/extractor/ruby/test/t6.rb delete mode 100644 src/main/antlr4/depends/extractor/ruby/test/t8.rb delete mode 100644 src/main/antlr4/depends/extractor/ruby/test/t9.rb delete mode 100755 src/main/antlr4/depends/extractor/ruby/test/test.rb delete mode 100644 src/main/antlr4/depends/extractor/ruby/test/throwcatch.rb delete mode 100644 src/main/antlr4/depends/extractor/ruby/test/truncked.rb delete mode 100644 src/main/antlr4/depends/extractor/ruby/test/unless.rb delete mode 100644 src/main/antlr4/depends/extractor/ruby/test/when.rb delete mode 100644 src/main/antlr4/depends/extractor/ruby/test/when_statement.rb delete mode 100755 src/main/antlr4/depends/extractor/ruby/test_all.sh delete mode 100755 src/main/antlr4/depends/extractor/ruby/test_all_in_computer.sh delete mode 100755 src/main/antlr4/depends/extractor/ruby/tokentest.sh delete mode 100755 src/main/antlr4/depends/extractor/ruby/tree.sh create mode 100644 src/main/java/depends/extractor/ruby/IncludedFileLocator.java create mode 100644 src/main/java/depends/extractor/ruby/RubyHandlerContext.java create mode 100644 src/main/java/depends/extractor/ruby/RubyParserHelper.java create mode 100644 src/test/java/depends/extractor/ruby/RubyParserTest.java create mode 100644 src/test/java/depends/extractor/ruby/RubyRequireTest.java create mode 100644 src/test/resources/ruby-code-examples/require_1.rb create mode 100644 src/test/resources/ruby-code-examples/require_2.rb diff --git a/.gitignore b/.gitignore index 0bc60b4..efa8fca 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,7 @@ *.log .idea/ out/ +data/ *.DS_Store /target/ .classpath diff --git a/data/undertestsrc/java/depends/DependsCommand.java b/data/undertestsrc/java/depends/DependsCommand.java new file mode 100644 index 0000000..85bb63d --- /dev/null +++ b/data/undertestsrc/java/depends/DependsCommand.java @@ -0,0 +1,76 @@ +package depends; + +import picocli.CommandLine.Command; +import picocli.CommandLine.Option; +import picocli.CommandLine.Parameters; + +@Command(name = "depends") +public class DependsCommand { + @Parameters(index = "0", description = "The lanauge of project files: [java, cpp]") + private String lang; + @Parameters(index = "1", description = "The directory to be analyzed") + private String src; + @Parameters(index = "2", description = "The output file name") + private String output; + @Option(names = {"-f", "--format"},split=",", description = "the output format: [json(default),xml,excel,detail(text format),dot]") + private String[] format=new String[]{"json"}; + @Option(names = {"-d", "--dir"}, description = "The output directory") + private String dir; + @Option(names = {"-m", "--map"}, description = "Output DV8 dependency map file.") + private boolean dv8map = true; + @Option(names = {"-s", "--strip-leading-path"}, description = "Strip the leading path.") + private boolean stripLeadingPath = false; + @Option(names = {"-g", "--granularity"}, description = "Granularity of dependency.[file(default),method]") + private String granularity="file"; + @Option(names = {"-p", "--namepattern"}, description = "The name path pattern.[default(/),dot(.)") + private String namePathPattern="default"; + @Option(names = {"-i","--includes"},split=",", description = "The files of searching path") + private String[] includes = new String[] {}; + @Option(names = {"-h","--help"}, usageHelp = true, description = "display this help and exit") + boolean help; + public String getLang() { + return lang; + } + public void setLang(String lang) { + this.lang = lang; + } + public String getSrc() { + return src; + } + public void setSrc(String src) { + this.src = src; + } + public String getOutputName() { + return output; + } + public void setOutput(String output) { + this.output = output; + } + public String[] getFormat() { + return format; + } + public String getOutputDir() { + if (dir==null) { + dir = System.getProperty("user.dir"); + } + return dir; + } + public boolean isDv8map() { + return dv8map; + } + public String[] getIncludes() { + return includes; + } + public boolean isHelp() { + return help; + } + public String getGranularity() { + return granularity; + } + public String getNamePathPattern() { + return namePathPattern; + } + public boolean isStripLeadingPath() { + return stripLeadingPath; + } +} diff --git a/data/undertestsrc/java/depends/Main.java b/data/undertestsrc/java/depends/Main.java new file mode 100644 index 0000000..7d19f54 --- /dev/null +++ b/data/undertestsrc/java/depends/Main.java @@ -0,0 +1,84 @@ +package depends; + +import java.io.File; +import java.nio.file.Files; + +import depends.addons.DV8MappingFileBuilder; +import depends.extractor.AbstractLangWorker; +import depends.extractor.LangWorkers; +import depends.extractor.cpp.CppWorker; +import depends.extractor.java.JavaWorker; +import depends.extractor.ruby.RubyWorker; +import depends.format.DependencyDumper; +import depends.format.path.DotPathFilenameWritter; +import depends.format.path.EmptyFilenameWritter; +import depends.matrix.DependencyGenerator; +import depends.matrix.FileDependencyGenerator; +import depends.matrix.FilenameWritter; +import depends.matrix.FunctionDependencyGenerator; +import depends.util.FileUtil; +import picocli.CommandLine; + +public class Main { + + public static void main(String[] args) { + try { + DependsCommand app = CommandLine.populateCommand(new DependsCommand(), args); + if (app.help) { + CommandLine.usage(new DependsCommand(), System.out); + System.exit(0); + } + executeCommand(app); + } catch (Exception e) { + System.err.println("Exception encountered"); + CommandLine.usage(new DependsCommand(), System.out); + System.exit(0); + } + + } + + private static void executeCommand(DependsCommand app) { + String lang = app.getLang(); + String inputDir = app.getSrc(); + String[] includeDir = app.getIncludes(); + String outputName = app.getOutputName(); + String outputDir = app.getOutputDir(); + String[] outputFormat = app.getFormat(); + if ( app.isDv8map()) { + DV8MappingFileBuilder dv8MapfileBuilder = new DV8MappingFileBuilder(); + dv8MapfileBuilder.create(outputDir+File.separator+"depends-dv8map.json"); + } + + inputDir = FileUtil.uniqFilePath(inputDir); + LangWorkers.getRegistry().register(new JavaWorker(inputDir, includeDir)); + LangWorkers.getRegistry().register(new CppWorker(inputDir, includeDir)); + LangWorkers.getRegistry().register(new RubyWorker(inputDir, includeDir)); + + AbstractLangWorker worker = LangWorkers.getRegistry().getWorkerOf(lang); + if (worker == null) { + System.out.println("Not support this language: " + lang); + return; + } + + long startTime = System.currentTimeMillis(); + DependencyGenerator dependencyGenerator = app.getGranularity().equals("file")? + (new FileDependencyGenerator()):(new FunctionDependencyGenerator()); + worker.setDependencyGenerator(dependencyGenerator); + worker.work(); + if (app.isStripLeadingPath()) { + worker.getDependencies().stripFilenames(inputDir); + } + + FilenameWritter filenameWritter = new EmptyFilenameWritter(); + if (app.getNamePathPattern().equals("dot")) { + filenameWritter = new DotPathFilenameWritter(); + } + worker.getDependencies().reWriteFilenamePattern(filenameWritter ); + DependencyDumper output = new DependencyDumper(worker.getDependencies(),worker.getErrors()); + output.outputResult(outputName,outputDir,outputFormat); + long endTime = System.currentTimeMillis(); + System.out.println("Consumed time: " + (float) ((endTime - startTime) / 1000.00) + " s, or " + + (float) ((endTime - startTime) / 60000.00) + " min."); + } + +} diff --git a/data/undertestsrc/java/depends/addons/DV8MappingFileBuilder.java b/data/undertestsrc/java/depends/addons/DV8MappingFileBuilder.java new file mode 100644 index 0000000..d404f62 --- /dev/null +++ b/data/undertestsrc/java/depends/addons/DV8MappingFileBuilder.java @@ -0,0 +1,79 @@ +package depends.addons; + +import java.io.File; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; + +import com.fasterxml.jackson.databind.ObjectMapper; + +import depends.deptypes.DependencyType; + +class MappingValue{ + int family = 0; + int vendor = 2; + int type = 0; + MappingValue(String orginalName, int typeId){ + this.type = typeId; + } + public int getFamily() { + return family; + } + public void setFamily(int family) { + this.family = family; + } + public int getVendor() { + return vendor; + } + public void setVendor(int vendor) { + this.vendor = vendor; + } + public int getType() { + return type; + } + public void setType(int type) { + this.type = type; + } +} + +class MappingItem { + String name; + MappingValue id; + public MappingItem(String dv8Name, int typeId) { + this.name = dv8Name; + String orginalName = dv8Name; + this.id = new MappingValue(orginalName, typeId); + } + public String getName() { + return name; + } + public void setName(String name) { + this.name = name; + } + public MappingValue getId() { + return id; + } + public void setId(MappingValue id) { + this.id = id; + } + +} + +public class DV8MappingFileBuilder { + + public void create(String fileName) { + Map values = new HashMap<>(); + ArrayList dependencies = DependencyType.allDependencies(); + for (int i=0;i allDependencies() { + ArrayList depedencyTypes = new ArrayList(); + depedencyTypes.add(IMPORT); + depedencyTypes.add(CONTAIN); + depedencyTypes.add(IMPLEMENT); + depedencyTypes.add(INHERIT); + depedencyTypes.add(CALL); + depedencyTypes.add(PARAMETER); + depedencyTypes.add(RETURN); + depedencyTypes.add(SET); + depedencyTypes.add(CREATE); + depedencyTypes.add(USE); + depedencyTypes.add(RECEIVE); + depedencyTypes.add(CAST); + depedencyTypes.add(THROW); + depedencyTypes.add(ANNOTATION); + return depedencyTypes; + } +} diff --git a/data/undertestsrc/java/depends/entity/AnonymousBlock.java b/data/undertestsrc/java/depends/entity/AnonymousBlock.java new file mode 100644 index 0000000..8758e50 --- /dev/null +++ b/data/undertestsrc/java/depends/entity/AnonymousBlock.java @@ -0,0 +1,9 @@ +package depends.entity; + +import java.util.UUID; + +public class AnonymousBlock extends ContainerEntity{ + public AnonymousBlock(Entity parent, Integer id) { + super(UUID.randomUUID().toString(), parent, id); + } +} diff --git a/data/undertestsrc/java/depends/entity/ContainerEntity.java b/data/undertestsrc/java/depends/entity/ContainerEntity.java new file mode 100644 index 0000000..b5779b7 --- /dev/null +++ b/data/undertestsrc/java/depends/entity/ContainerEntity.java @@ -0,0 +1,235 @@ +package depends.entity; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import depends.extractor.java.JavaParser.ExpressionContext; +import depends.relations.Inferer; + +/** + * ContainerEntity for example file, class, method, etc. + * they could contain vars, functions, ecpressions, type parameters, etc. + */ +public abstract class ContainerEntity extends Entity { + private static final Logger logger = LoggerFactory.getLogger(ContainerEntity.class); + + private ArrayList vars; + private ArrayList functions; + private HashMap expressions; + private Collection typeParameters; // Generic type parameters like , , + private Collection annotations = new ArrayList<>(); + private Collection resolvedTypeParameters = new ArrayList<>(); + private Collection resolvedAnnotations = new ArrayList<>(); + + public ContainerEntity(String rawName, Entity parent, Integer id) { + super(rawName, parent, id); + vars = new ArrayList<>(); + functions = new ArrayList<>(); + expressions = new HashMap<>(); + typeParameters = new ArrayList<>(); + } + + public void addAnnotation(String name) { + this.annotations.add(name); + } + + public void addTypeParameter(String typeName) { + this.typeParameters.add(typeName); + } + + public void addTypeParameter(List parameters) { + this.typeParameters.addAll(parameters); + } + + public void addVar(VarEntity var) { + if (logger.isDebugEnabled()) { + logger.debug("var found: "+var.getRawName() + ":" + var.getRawType()); + } + this.vars.add(var); + } + + public ArrayList getVars() { + return this.vars; + } + + public void addFunction(FunctionEntity functionEntity) { + this.functions.add(functionEntity); + } + + public ArrayList getFunctions() { + return this.functions; + } + + public HashMap expressions() { + return expressions; + } + + public void addExpression(Object key, Expression expression) { + expressions.put(key, expression); + } + + /** + * A common utility function used to transfer the identifiers + * to types. + * @param inferer - the inferer object + * @param identifiers - the identifiers will be translated + * @return The translated Types + */ + protected Collection identiferToTypes(Inferer inferer, Collection identifiers) { + ArrayList r = new ArrayList<>(); + for (String typeParameter : identifiers) { + TypeEntity typeEntity = inferer.inferTypeFromName(this, typeParameter); + if (typeEntity==null) { + if (((ContainerEntity)getParent()).isGenericTypeParameter(typeParameter)) { + typeEntity = Inferer.genericParameterType; + } + } + if (typeEntity != null) + r.add(typeEntity); + } + return r; + } + + /** + * For all data in the class, infer their types. + * Should be override in sub-classes + */ + public void inferLocalLevelEntities(Inferer inferer) { + resolvedTypeParameters = identiferToTypes(inferer, typeParameters); + resolvedAnnotations = identiferToTypes(inferer, annotations); + for (VarEntity var : this.vars) { + var.inferLocalLevelEntities(inferer); + } + for (FunctionEntity func:this.functions) { + func.inferLocalLevelEntities(inferer); + } + } + + /** + * Resolve all expression's type + * @param inferer + */ + public void resolveExpressions(Inferer inferer) { + for (Expression expression : expressions.values()) { + //1. if expression's type existed, break; + if (expression.getType() != null) + continue; + + //2. if expression's rawType existed, directly infer type by rawType + // if expression's rawType does not existed, infer type based on identifiers + if (expression.rawType != null) { + expression.setType(inferer.inferTypeFromName(this, expression.rawType),null,inferer); + }else if (expression.isDot){ //wait for previous + continue; + } else if (expression.rawType!=null) { + expression.setType(inferer.inferTypeFromName(this, expression.rawType),null,inferer); + if (expression.getType() !=null) { + continue; + } + } + if (expression.identifier!=null) { + Entity entity = inferer.resolveName(this, expression.identifier, true); + if (entity!=null) { + expression.setType(entity.getType(),entity,inferer); + continue; + } + if (expression.isCall) { + FunctionEntity func = this.lookupFunctionInVisibleScope(expression.identifier); + if (func!=null) { + expression.setType(func.getType(),func,inferer); + } + }else { + + VarEntity varEntity = this.lookupVarsInVisibleScope(expression.identifier); + if (varEntity!=null) { + expression.setType( varEntity.getType(),varEntity,inferer); + } + } + } + } + } + + + + + public Collection getResolvedTypeParameters() { + return resolvedTypeParameters; + } + + + public Collection getResolvedAnnotations() { + return resolvedAnnotations; + } + + + public String dumpExpressions() { + StringBuilder sb = new StringBuilder(); + for (Expression exp:expressions.values()) { + sb.append(exp.toString()).append("\n"); + } + return sb.toString(); + } + + + + public boolean isGenericTypeParameter(String rawType) { + if (this.typeParameters.contains(rawType)) return true; + if (this.getParent()==null || !(this.getParent() instanceof ContainerEntity)) + return false; + return ((ContainerEntity)getParent()).isGenericTypeParameter(rawType); + } + + protected FunctionEntity lookupFunctionLocally(String functionName) { + for (FunctionEntity func : getFunctions()) { + if (func.getRawName().equals(functionName)) + return func; + } + return null; + } + + public FunctionEntity lookupFunctionInVisibleScope(String functionName) { + ContainerEntity fromEntity = this; + while (fromEntity != null) { + if (fromEntity instanceof ContainerEntity) { + FunctionEntity func = ((ContainerEntity) fromEntity).lookupFunctionLocally(functionName); + if (func != null) + return func; + } + fromEntity = (ContainerEntity) this.getAncestorOfType(ContainerEntity.class); + } + return null; + } + + /** + * To found the var. Must be invoked after all entities var binding solved + * @param fromEntity + * @param varName + * @return + */ + public VarEntity lookupVarsInVisibleScope(String varName) { + + ContainerEntity fromEntity = this; + while (fromEntity != null) { + if (fromEntity instanceof ContainerEntity) { + VarEntity var = ((ContainerEntity) fromEntity).lookupVarLocally(varName); + if (var != null) + return var; + } + fromEntity = (ContainerEntity) this.getAncestorOfType(ContainerEntity.class); + } + return null; + } + + private VarEntity lookupVarLocally(String varName) { + for (VarEntity var:getVars()) { + if (var.getRawName().equals(varName)) + return var; + } + return null; + } +} diff --git a/data/undertestsrc/java/depends/entity/EmptyTypeEntity.java b/data/undertestsrc/java/depends/entity/EmptyTypeEntity.java new file mode 100644 index 0000000..88acb4a --- /dev/null +++ b/data/undertestsrc/java/depends/entity/EmptyTypeEntity.java @@ -0,0 +1,9 @@ +package depends.entity; + +public class EmptyTypeEntity extends TypeEntity { + + public EmptyTypeEntity() { + super("", null, -1); + } + +} diff --git a/data/undertestsrc/java/depends/entity/Entity.java b/data/undertestsrc/java/depends/entity/Entity.java new file mode 100644 index 0000000..cd37947 --- /dev/null +++ b/data/undertestsrc/java/depends/entity/Entity.java @@ -0,0 +1,152 @@ +package depends.entity; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashSet; +import java.util.Set; + +import depends.relations.Inferer; +import depends.relations.Relation; + +/** + * Entity is the root of all entities, including file, package, module, + * class, method/function etc. + * Each entity has unique id, name,qualifiedName, parent, children + * We also use entity to record relations + */ +public abstract class Entity { + int id=-1; + String qualifiedName = null; + String rawName = ""; + Entity parent; + Set children = new HashSet<>(); + ArrayList relations = new ArrayList<>(); + + + public Entity(String rawName, Entity parent, Integer id) { + this.qualifiedName = null; + this.rawName = rawName; + this.parent = parent; + this.id = id; + if (parent!=null) + parent.children.add(this); + deduceQualifiedName(); + } + + /** + * Rule 1: if it contains '.' , then the name is equal to raw name + * Rule 2: if parent not exists, the name is equal to raw name + * Rule 3: if parent exists but no qualified name exists or empty, the name is equal to raw name + * Rule 4: otherwise, qualified name = parent_qualfied_name + "."+rawName + * Rule 5: make sure the qualified name do not start with '.' + * TODO: the Rule 1 should be further check. Maybe issue exists - (C++中的ClassName::MethodName()会不会有问题? + */ + private void deduceQualifiedName() { + rawName = rawName.replace("::","." ); + if (this.rawName.contains(".")) { + this.qualifiedName = this.rawName; + return; //already qualified + } + if (parent==null) { + this.qualifiedName = this.rawName; + return; + } + if (parent.getQualifiedName()==null) { + this.qualifiedName = this.rawName; + return; + } + if (parent.getQualifiedName().isEmpty()) { + this.qualifiedName = rawName; + return; + } + this.qualifiedName= parent.getQualifiedName()+"." + rawName; + if (rawName.startsWith(".")) { + rawName = rawName.substring(2); + } + } + + + public String getRawName() { + return rawName; + } + + public int getId() { + return id; + } + + public void addRelation(Relation relation) { + relations.add(relation); + } + + public ArrayList getRelations() { + return relations; + } + + public void addChild(Entity child) { + children.add(child); + } + + public Entity getParent() { + return parent; + } + + public void setParent(Entity parent) { + this.parent = parent; + } + + public Collection getChildren() { + return children; + } + + public void setQualifiedName(String qualifiedName) { + this.qualifiedName = qualifiedName; + } + + public void setRawName(String rawName) { + this.rawName = rawName; + } + + public String getQualifiedName() { + return qualifiedName; + } + + @Override + public String toString() { + return "Entity [id=" + id + ", qualifiedName=" + qualifiedName + ", rawName=" + rawName + "]"; + } + + /** + * Get ancestor of type. + * @param classType + * @return null (if not exist) or the type + */ + public Entity getAncestorOfType(@SuppressWarnings("rawtypes") Class classType) { + Entity fromEntity = this; + while(fromEntity!=null) { + if (fromEntity.getClass().equals(classType)) + return fromEntity; + if (fromEntity.getParent()==null) return null; + fromEntity = fromEntity.getParent(); + } + return null; + } + + /** + * Invoke inferer to resolve the entity type etc. + * */ + public void inferEntities(Inferer inferer) { + inferLocalLevelEntities(inferer); + for (Entity child:children) { + child.inferEntities(inferer); + } + } + public abstract void inferLocalLevelEntities(Inferer inferer); + + public TypeEntity getType() { + return null; + } + + public String getDisplayName() { + return getRawName(); + } +} diff --git a/data/undertestsrc/java/depends/entity/Expression.java b/data/undertestsrc/java/depends/entity/Expression.java new file mode 100644 index 0000000..24015f4 --- /dev/null +++ b/data/undertestsrc/java/depends/entity/Expression.java @@ -0,0 +1,107 @@ +package depends.entity; + +import depends.relations.Inferer; + +public class Expression { + public Integer id; + public Integer parentId; + public Integer deduceTypeBasedId; //by default, parent expression type determined by most left child + public Expression parent; + public String text; // for debug purpose + public String rawType; //the raw type name + public String identifier; // the varName, or method name, etc. + public boolean isSet = false; // is a set relation from right to leftHand + public boolean isDot = false; // is a dot expression, will decuce variable tfype left to right + public boolean isCall = false; + public boolean isLogic = false; + public boolean isCreate = false; + public boolean isCast = false; + public boolean deriveTypeFromChild = true; + + private TypeEntity type; // the type we care - for relation calculation. + //for leaf, it equals to referredEntity.getType. otherwise, depends on child's type strategy + private Entity referredEntity; + public TypeEntity getType() { + return type; + } + + public void setType(TypeEntity type, Entity referredEntity, Inferer inferer) { + if (this.type!=null) return; + this.type = type; + this.referredEntity = referredEntity; + if (this.referredEntity==null) + this.referredEntity = type; + deduceParentType(inferer); + } + + public Expression(Integer id, Integer parentId) { + this.id = id; + this.parentId = parentId; + } + + @Override + public String toString() { + StringBuilder s = new StringBuilder(); + s.append("[").append(text).append("]").append("|") + .append("rawType:").append(rawType).append("|") + .append("identifier:").append(identifier).append("|") + .append("prop:").append(isDot?"[dot]":"") + .append(isSet?"[set]":"") + .append(isLogic?"[bool]":"") + .append(isCall?"[call]":"").append("|") + .append("parent:").append(parent==null?"none":parent.text) + .append("type:").append(type).append("|"); + return s.toString(); + } + + /** + * deduce type of parent based on child's type + * @param expressionList + * @param inferer + */ + public void deduceParentType(Inferer inferer) { + if (this.type==null) return; + if (this.parent==null) return; + Expression parent = this.parent; + if (parent.type != null)return; + if (!parent.deriveTypeFromChild) return; + //parent's type depends on first child's type + if (parent.deduceTypeBasedId!=this.id) return; + + //if child is a built-in/external type, then parent must also a built-in/external type + if (this.type.equals(Inferer.buildInType)) { + parent.setType(Inferer.buildInType,Inferer.buildInType,inferer); + return; + }else if (this.type.equals(Inferer.externalType)){ + parent.setType(Inferer.externalType,Inferer.externalType,inferer); + return; + } + + /* if it is a logic expression, the return type/type is boolean. */ + if (parent.isLogic) { + parent.setType(Inferer.buildInType,null,inferer); + } + /* if it is a.b, and we already get a's type, b's type could be identified easily */ + else if (parent.isDot) { + if (parent.isCall) { + FunctionEntity func = this.getType().lookupFunctionInVisibleScope(parent.identifier); + if (func!=null) + parent.setType(func.getType(), func,inferer); + }else { + parent.setType(inferer.inferTypeFromName(this.getType(), parent.identifier),null,inferer); + if (parent.type!=null) return; + VarEntity var = this.getType().lookupVarsInVisibleScope(parent.identifier); + if (var!=null) + parent.setType(var.getType(),var, inferer); + } + } + /* if other situation, simple make the parent and child type same */ + else { + parent.setType(type, null, inferer); + } + } + + public Entity getReferredEntity() { + return referredEntity; + } +} \ No newline at end of file diff --git a/data/undertestsrc/java/depends/entity/FileEntity.java b/data/undertestsrc/java/depends/entity/FileEntity.java new file mode 100644 index 0000000..2005bd7 --- /dev/null +++ b/data/undertestsrc/java/depends/entity/FileEntity.java @@ -0,0 +1,89 @@ +package depends.entity; + +import java.util.ArrayList; +import java.util.List; + +import depends.importtypes.Import; +import depends.relations.Inferer; + +public class FileEntity extends ContainerEntity { + private List importedNames = new ArrayList<>(); + private boolean isInProjectScope = false; + private List importedRelationEntities = new ArrayList<>(); + private List importedFiles = new ArrayList<>(); + private List importedTypes = new ArrayList<>(); + + public FileEntity(String fullName, int fileId, boolean isInProjectScope) { + super(fullName, null, fileId); + setQualifiedName(fullName); + } + + public FileEntity(String fullName, int fileId) { + this(fullName, fileId, true); + } + + public void addImport(Import imported) { + importedNames.add(imported); + } + + /** + * To match the imported name by suffix + * for example: + * import a.b.ClassX; + * the b.ClassX, ClassX , a.b.classX should be matched + * @param lastName + * @return + */ + public String importedSuffixMatch(String lastName) { + if (!lastName.startsWith(".")) + lastName = "." + lastName; + for (Entity imported : this.importedTypes) { + String name = imported.getQualifiedName(); + if (!name.startsWith(".")) + name = "." + name; + if (imported.getQualifiedName().endsWith(lastName)) + return imported.getQualifiedName(); + } + return null; + } + + @Override + public String getQualifiedName() { + if (this.getParent() == null) { + return ""; + } + if (this.getParent() instanceof PackageEntity) + return this.getParent().getQualifiedName(); + else + return super.getQualifiedName(); + } + + @Override + public void inferLocalLevelEntities(Inferer inferer) { + this.importedRelationEntities = inferer.getImportedRelationEntities(importedNames); + this.importedTypes = inferer.getImportedTypes(importedNames); + this.importedFiles = inferer.getImportedFiles(importedNames); + super.inferLocalLevelEntities(inferer); + } + + public boolean isInProjectScope() { + return isInProjectScope; + } + + public void setInProjectScope(boolean isInProjectScope) { + this.isInProjectScope = isInProjectScope; + } + + public List getImportedRelationEntities() { + return importedRelationEntities; + } + + public List getImportedFiles() { + return importedFiles; + } + + public List getImportedTypes() { + return importedTypes; + } + +} diff --git a/data/undertestsrc/java/depends/entity/FunctionEntity.java b/data/undertestsrc/java/depends/entity/FunctionEntity.java new file mode 100644 index 0000000..63e95c6 --- /dev/null +++ b/data/undertestsrc/java/depends/entity/FunctionEntity.java @@ -0,0 +1,78 @@ +package depends.entity; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +import depends.relations.Inferer; + +public class FunctionEntity extends ContainerEntity{ + private List returnTypeIdentifiers = new ArrayList<>(); + Collection parameters; + Collection throwTypesIdentifiers = new ArrayList<>(); + private Collection returnTypes = new ArrayList<>(); + private TypeEntity returnType; + private Collection throwTypes = new ArrayList<>(); + public FunctionEntity(String simpleName, Entity parent, Integer id, String returnType) { + super(simpleName, parent,id); + this.returnTypes = new ArrayList<>(); + returnTypeIdentifiers = new ArrayList<>(); + this.parameters = new ArrayList<>(); + throwTypesIdentifiers = new ArrayList<>(); + addReturnType(returnType); + } + public Collection getReturnTypes() { + return returnTypes; + } + + @Override + public TypeEntity getType() { + return returnType; + } + + public void addReturnType(String returnType) { + this.returnTypeIdentifiers.add(returnType); + } + public void addThrowTypes(List throwedType) { + throwTypesIdentifiers.addAll(throwedType); + } + + @Override + public void inferLocalLevelEntities(Inferer inferer) { + for (VarEntity param:parameters) { + param.inferLocalLevelEntities(inferer); + } + returnTypes= identiferToTypes(inferer,this.returnTypeIdentifiers); + if (returnTypes.size()>0) + returnType = returnTypes.iterator().next(); + + throwTypes= identiferToTypes(inferer,this.throwTypesIdentifiers); + super.inferLocalLevelEntities(inferer); + } + public Collection getParameters() { + return parameters; + } + public Collection getThrowTypes() { + return throwTypes; + } + @Override + public VarEntity lookupVarsInVisibleScope(String varName) { + for (VarEntity param:parameters) { + if (varName.equals(param.getRawName())) { + return param; + } + } + return super.lookupVarsInVisibleScope(varName); + } + public void addParameter(VarEntity var) { + this.parameters.add(var); + } + public void setReturnType(TypeEntity returnType) { + this.returnType = returnType; + } + @Override + public String getDisplayName() { + FileEntity f = (FileEntity) this.getAncestorOfType(FileEntity.class); + return f.getRawName()+"("+getRawName()+")"; + } +} diff --git a/data/undertestsrc/java/depends/entity/MultiDeclareEntities.java b/data/undertestsrc/java/depends/entity/MultiDeclareEntities.java new file mode 100644 index 0000000..a30bd44 --- /dev/null +++ b/data/undertestsrc/java/depends/entity/MultiDeclareEntities.java @@ -0,0 +1,55 @@ +package depends.entity; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +import depends.relations.Inferer; + +/** + * MultiDeclareEntity is a special container, which is used as a wrapper + * of multi-declaration. for example, + * in C++, a function could be declared in different place with the same signature. + */ +public class MultiDeclareEntities extends ContainerEntity { + List entities = new ArrayList<>(); + public MultiDeclareEntities(Entity entity, int id ) { + super(entity.getRawName(), entity.getParent(), id); + if (entity instanceof ContainerEntity) + entities.add((ContainerEntity)entity); + } + + @Override + public void inferLocalLevelEntities(Inferer inferer) { + for (Entity entity:entities) { + entity.inferLocalLevelEntities(inferer); + } + } + + public void add(Entity entity) { + if (entity instanceof ContainerEntity) + entities.add((ContainerEntity)entity); + } + + public List getEntities() { + return entities; + } + + @Override + public Collection getChildren() { + List children = new ArrayList<>(); + for (Entity entity:entities) { + children.addAll(entity.getChildren()); + } + return children; + } + + @Override + public TypeEntity getType() { + for (Entity entity:entities) { + if(entity.getType()!=null); + return entity.getType(); + } + return null; + } +} diff --git a/data/undertestsrc/java/depends/entity/PackageEntity.java b/data/undertestsrc/java/depends/entity/PackageEntity.java new file mode 100644 index 0000000..f463c91 --- /dev/null +++ b/data/undertestsrc/java/depends/entity/PackageEntity.java @@ -0,0 +1,12 @@ +package depends.entity; + +public class PackageEntity extends TypeEntity { + public PackageEntity(String rawName, Integer id) { + super(rawName, null,id); + setQualifiedName(rawName); //in Java, package raw name = full name + } + + public PackageEntity(String rawName, FileEntity currentFile, Integer id) { + super(rawName, currentFile,id); + } +} diff --git a/data/undertestsrc/java/depends/entity/TypeAliasEntity.java b/data/undertestsrc/java/depends/entity/TypeAliasEntity.java new file mode 100644 index 0000000..e67d1ad --- /dev/null +++ b/data/undertestsrc/java/depends/entity/TypeAliasEntity.java @@ -0,0 +1,43 @@ +package depends.entity; + +import java.util.Collection; + +import depends.relations.Inferer; + +public class TypeAliasEntity extends TypeEntity{ + TypeEntity originType = new EmptyTypeEntity(); + String originTypeName; + public TypeAliasEntity(String simpleName, Entity parent, Integer id, String originTypeName) { + super(simpleName, parent, id); + this.originTypeName = originTypeName; + } + @Override + public void inferLocalLevelEntities(Inferer inferer) { + Entity entity = inferer.resolveName(this, originTypeName, true); + TypeEntity type = null; + if (entity!=null) + type = entity.getType(); + if (type!=null) + originType = type; + if (type == this) { + System.err.println("cannot typedef as self"); + } + originType.inferLocalLevelEntities(inferer); + } + @Override + public Collection getInheritedTypes() { + return originType.getInheritedTypes(); + } + @Override + public Collection getImplementedTypes() { + return originType.getImplementedTypes(); + } + @Override + public TypeEntity getInheritedType() { + return originType.getInheritedType(); + } + public TypeEntity getOriginType() { + return originType; + } + +} diff --git a/data/undertestsrc/java/depends/entity/TypeEntity.java b/data/undertestsrc/java/depends/entity/TypeEntity.java new file mode 100644 index 0000000..6b6275f --- /dev/null +++ b/data/undertestsrc/java/depends/entity/TypeEntity.java @@ -0,0 +1,72 @@ +package depends.entity; + +import java.util.ArrayList; +import java.util.Collection; + +import depends.relations.Inferer; + +public class TypeEntity extends ContainerEntity{ + Collection inheritedTypes = new ArrayList<>(); + Collection implementedTypes = new ArrayList<>(); + Collection inhertedTypeIdentifiers; + Collection implementedIdentifiers; + TypeEntity inheritedType; + + public TypeEntity(String simpleName, Entity parent, Integer id) { + super(simpleName,parent,id); + inhertedTypeIdentifiers = new ArrayList<>(); + implementedIdentifiers = new ArrayList<>(); + } + @Override + public void inferLocalLevelEntities(Inferer inferer) { + inheritedTypes= identiferToTypes(inferer,this.inhertedTypeIdentifiers); + implementedTypes= identiferToTypes(inferer,this.implementedIdentifiers); + if (inheritedTypes.size()>0) + inheritedType = inheritedTypes.iterator().next(); + super.inferLocalLevelEntities(inferer); + } + public void addImplements(String typeName) { + if (typeName.equals(this.getRawName())) return; + if (implementedIdentifiers.contains(typeName)) return; + this.implementedIdentifiers.add(typeName); + } + public void addExtends(String typeName) { + if (typeName.equals(this.getRawName())) return; + if (inhertedTypeIdentifiers.contains(typeName)) return; + this.inhertedTypeIdentifiers.add(typeName); + } + public Collection getInheritedTypes() { + return inheritedTypes; + } + + public Collection getImplementedTypes() { + return implementedTypes; + } + + public TypeEntity getInheritedType() { + return inheritedType; + } + + @Override + protected FunctionEntity lookupFunctionLocally(String functionName) { + FunctionEntity funcType = super.lookupFunctionLocally(functionName); + if (funcType!=null) return funcType; + for (TypeEntity inhertedType : getInheritedTypes()) { + funcType = inhertedType.lookupFunctionLocally(functionName); + if (funcType == null) + break; + } + if (funcType != null) + return funcType; + for (TypeEntity implType : getImplementedTypes()) { + funcType = implType.lookupFunctionLocally( functionName); + if (funcType == null) + break; + } + return funcType; + } + @Override + public TypeEntity getType() { + return this; + } +} diff --git a/data/undertestsrc/java/depends/entity/VarEntity.java b/data/undertestsrc/java/depends/entity/VarEntity.java new file mode 100644 index 0000000..9b0728d --- /dev/null +++ b/data/undertestsrc/java/depends/entity/VarEntity.java @@ -0,0 +1,37 @@ +package depends.entity; + +import depends.relations.Inferer; + +public class VarEntity extends Entity { + private String rawType; + private TypeEntity type; + public VarEntity(String simpleName, String rawType, Entity parent, int id) { + super(simpleName, parent,id); + this.rawType = rawType; + } + + public String getRawType() { + return rawType; + } + + @Override + public TypeEntity getType() { + return type; + } + + public void setType(TypeEntity type) { + this.type = type; + } + + @Override + public void inferLocalLevelEntities(Inferer inferer) { + Entity entity = inferer.resolveName(this, rawType, true); + if (entity==null) return; + type = entity.getType(); + if (type==null) { + if (((ContainerEntity)getParent()).isGenericTypeParameter(rawType)) { + type = Inferer.genericParameterType; + } + } + } +} diff --git a/data/undertestsrc/java/depends/entity/repo/BuiltInType.java b/data/undertestsrc/java/depends/entity/repo/BuiltInType.java new file mode 100644 index 0000000..a060d7b --- /dev/null +++ b/data/undertestsrc/java/depends/entity/repo/BuiltInType.java @@ -0,0 +1,38 @@ +package depends.entity.repo; + +import java.util.HashSet; +import java.util.Set; + +import depends.relations.Inferer; + +public abstract class BuiltInType { + + + public void createBuiltInTypes() { + for(String prefix:getBuiltInPrefixStr()) { + builtInPrefix.add(prefix); + } + for (String type:getBuiltInTypeStr()) { + builtInType.add(type); + } + } + + public abstract String[] getBuiltInTypeStr(); + public abstract String[] getBuiltInPrefixStr() ; + + private Set builtInType = new HashSet<>(); + private Set builtInPrefix = new HashSet<>(); + + public boolean isBuiltInType(String type) { + if (Inferer.buildInType.getRawName().equals(type)) return true; + return builtInType.contains(type); + } + + public boolean isBuiltInTypePrefix(String type) { + for (String prefix:builtInPrefix) { + if (type.startsWith(prefix)) return true; + } + return false; + } + +} diff --git a/data/undertestsrc/java/depends/entity/repo/EntityNotExistsException.java b/data/undertestsrc/java/depends/entity/repo/EntityNotExistsException.java new file mode 100644 index 0000000..c9e35bf --- /dev/null +++ b/data/undertestsrc/java/depends/entity/repo/EntityNotExistsException.java @@ -0,0 +1,11 @@ +package depends.entity.repo; + +public class EntityNotExistsException extends Exception { + + private static final long serialVersionUID = 8897694627699543193L; + + public EntityNotExistsException(int entityId) { + super("given id "+ entityId + " not exists."); + } + +} diff --git a/data/undertestsrc/java/depends/entity/repo/EntityRepo.java b/data/undertestsrc/java/depends/entity/repo/EntityRepo.java new file mode 100644 index 0000000..b3d99ab --- /dev/null +++ b/data/undertestsrc/java/depends/entity/repo/EntityRepo.java @@ -0,0 +1,54 @@ +package depends.entity.repo; + +import java.util.Collection; +import java.util.HashMap; + +import depends.entity.Entity; +import depends.entity.MultiDeclareEntities; + +public class EntityRepo extends IdGenerator{ + public HashMap allEntieisByName = new HashMap<>(); + public HashMap allEntitiesById = new HashMap<>(); + + public EntityRepo() { + } + + public Entity getEntity(String entityName) { + return allEntieisByName.get(entityName); + } + + public Entity getEntity(Integer entityId) { + return allEntitiesById.get(entityId); + } + + public void add(Entity entity) { + allEntitiesById.put(entity.getId(), entity); + String name = entity.getRawName(); + if (entity.getQualifiedName()!=null && !(entity.getQualifiedName().isEmpty()) ) { + name = entity.getQualifiedName(); + } + if (allEntieisByName.containsKey(name)) { + Entity existedEntity = allEntieisByName.get(name); + if (existedEntity instanceof MultiDeclareEntities) { + ((MultiDeclareEntities)existedEntity).add(entity); + }else { + MultiDeclareEntities eMultiDeclare = new MultiDeclareEntities(existedEntity,this.generateId()); + eMultiDeclare.add(entity); + allEntieisByName.put(name, eMultiDeclare); + } + }else { + allEntieisByName.put(name, entity); + } + if (entity.getParent()!=null) + this.setParent(entity, entity.getParent()); + } + + public Collection getEntities() { + return allEntitiesById.values(); + } + + public void setParent(Entity child, Entity parent) { + child.setParent(parent); + parent.addChild(child); + } +} diff --git a/data/undertestsrc/java/depends/entity/repo/IdGenerator.java b/data/undertestsrc/java/depends/entity/repo/IdGenerator.java new file mode 100644 index 0000000..c6e1c93 --- /dev/null +++ b/data/undertestsrc/java/depends/entity/repo/IdGenerator.java @@ -0,0 +1,15 @@ +package depends.entity.repo; + +public class IdGenerator { + private int nextAvaliableIndex; + public IdGenerator() { + nextAvaliableIndex = 0; + } + /** + * Generate a global unique ID for entity + * @return the unique id + */ + public Integer generateId() { + return nextAvaliableIndex++; + } +} diff --git a/data/undertestsrc/java/depends/entity/repo/NoRequestedTypeOfAncestorExistsException.java b/data/undertestsrc/java/depends/entity/repo/NoRequestedTypeOfAncestorExistsException.java new file mode 100644 index 0000000..bcf1ac3 --- /dev/null +++ b/data/undertestsrc/java/depends/entity/repo/NoRequestedTypeOfAncestorExistsException.java @@ -0,0 +1,12 @@ +package depends.entity.repo; + +public class NoRequestedTypeOfAncestorExistsException extends Exception { + + private static final long serialVersionUID = -5951549776366770294L; + + public NoRequestedTypeOfAncestorExistsException(int entityId, @SuppressWarnings("rawtypes") Class classType) { + super("the given type of " + classType.getCanonicalName() + " for " + + entityId + " does not exists."); + } + +} diff --git a/data/undertestsrc/java/depends/entity/repo/NullBuiltInType.java b/data/undertestsrc/java/depends/entity/repo/NullBuiltInType.java new file mode 100644 index 0000000..0e5a13d --- /dev/null +++ b/data/undertestsrc/java/depends/entity/repo/NullBuiltInType.java @@ -0,0 +1,15 @@ +package depends.entity.repo; + +public class NullBuiltInType extends BuiltInType { + + @Override + public String[] getBuiltInTypeStr() { + return new String[] {}; + } + + @Override + public String[] getBuiltInPrefixStr() { + return new String[] {}; + } + +} diff --git a/data/undertestsrc/java/depends/extractor/AbstractLangWorker.java b/data/undertestsrc/java/depends/extractor/AbstractLangWorker.java new file mode 100644 index 0000000..81ebd6f --- /dev/null +++ b/data/undertestsrc/java/depends/extractor/AbstractLangWorker.java @@ -0,0 +1,114 @@ +package depends.extractor; + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.Set; + +import org.codehaus.plexus.util.FileUtils; + +import depends.entity.repo.EntityRepo; +import depends.matrix.DependencyGenerator; +import depends.matrix.DependencyMatrix; +import depends.relations.Inferer; +import depends.util.FileTraversal; +abstract public class AbstractLangWorker { + public abstract String supportedLanguage(); + public abstract String[] fileSuffixes(); + protected Inferer inferer; + protected EntityRepo entityRepo; + DependencyMatrix dependencyMatrix; + private String inputSrcPath; + private String[] includeDirs; + private DependencyGenerator dependencyGenerator; + + public AbstractLangWorker(String inputDir, String[] includeDir) { + entityRepo = new EntityRepo(); + this.inputSrcPath = inputDir; + this.includeDirs = includeDir; + } + + + public void work() { + parseAllFiles(); + resolveBindings(); + identifyDependencies(); + } + + /** + * Errors during all execution steps. could be extend as several methods in future + * @return + */ + public abstract List getErrors(); + /** + * + * @return unsolved bindings + */ + protected void resolveBindings() { + System.out.println("Resolve types and bindings of variables, methods and expressions...."); + Set unsolved = inferer.resolveAllBindings(); + if (unsolved.size()>0) + System.err.println("The following items are unsolved." + unsolved); + System.out.println("types and bindings resolved successfully..."); + } + + private void identifyDependencies(){ + System.out.println("dependencie data generating..."); + dependencyMatrix = dependencyGenerator.build(entityRepo); + dependencyMatrix.remapIds(entityRepo); + System.out.println("dependencie data generating done successfully..."); + } + + private final void parseAllFiles() { + System.out.println("start parsing files..."); + FileTraversal fileTransversal = new FileTraversal(new FileTraversal.IFileVisitor(){ + @Override + public void visit(File file) { + FileParser fileParser = getFileParser(file.getAbsolutePath()); + try { + System.out.println("parsing " + file.getAbsolutePath() + + "..."); + fileParser.parse(); + } catch (IOException e) { + e.printStackTrace(); + } + } + + }); + fileTransversal.extensionFilter(this.fileSuffixes()); + fileTransversal.travers(this.inputSrcPath); + System.out.println("all files procceed successfully..."); + + } + + protected abstract FileParser getFileParser(String fileFullPath); + + public List includePaths() { + ArrayList r = new ArrayList(); + for (String path:includeDirs) { + if (FileUtils.fileExists(path)) { + if (!r.contains(path)) + r.add(path); + } + path = this.inputSrcPath +File.separator+path; + if (FileUtils.fileExists(path)) { + if (!r.contains(path)) + r.add(path); + } + } + return r; + } + + public DependencyMatrix getDependencies() { + return dependencyMatrix; + } + public EntityRepo getEntityRepo() { + return this.entityRepo; + } + + public void setDependencyGenerator(DependencyGenerator dependencyGenerator) { + this.dependencyGenerator = dependencyGenerator; + } + +} diff --git a/data/undertestsrc/java/depends/extractor/FileParser.java b/data/undertestsrc/java/depends/extractor/FileParser.java new file mode 100644 index 0000000..2ae3dc8 --- /dev/null +++ b/data/undertestsrc/java/depends/extractor/FileParser.java @@ -0,0 +1,8 @@ +package depends.extractor; + +import java.io.IOException; + +public interface FileParser { + void parse() throws IOException; + +} diff --git a/data/undertestsrc/java/depends/extractor/HandlerContext.java b/data/undertestsrc/java/depends/extractor/HandlerContext.java new file mode 100644 index 0000000..3a016b2 --- /dev/null +++ b/data/undertestsrc/java/depends/extractor/HandlerContext.java @@ -0,0 +1,178 @@ +package depends.extractor; + +import java.util.List; +import java.util.Stack; + +import depends.entity.ContainerEntity; +import depends.entity.Entity; +import depends.entity.FileEntity; +import depends.entity.FunctionEntity; +import depends.entity.TypeAliasEntity; +import depends.entity.TypeEntity; +import depends.entity.VarEntity; +import depends.entity.repo.EntityRepo; +import depends.entity.repo.IdGenerator; +import depends.importtypes.Import; + +public abstract class HandlerContext { + protected EntityRepo entityRepo; + protected IdGenerator idGenerator; + + protected FileEntity currentFileEntity; + + + public HandlerContext(EntityRepo entityRepo) { + this.entityRepo = entityRepo; + this.idGenerator = entityRepo; + entityStack = new Stack(); + } + + public FileEntity startFile(String fileName) { + currentFileEntity = new FileEntity(fileName, idGenerator.generateId(),true); + pushToStack(currentFileEntity); + entityRepo.add(currentFileEntity); + return currentFileEntity; + } + + + + public Entity foundNewType(String classOrInterfaceName) { + TypeEntity currentTypeEntity = new TypeEntity(classOrInterfaceName, this.latestValidContainer(), + idGenerator.generateId()); + pushToStack(currentTypeEntity); + entityRepo.add(currentTypeEntity); + return currentTypeEntity; + } + + public void foundNewTypeAlias(String aliasName, String originalName) { + if (aliasName.equals(originalName)) return; //it is a tricky, we treat same name no different. + //indeed it is not perfect -> the right match should depends on no-bare format like "struct a" instead of "a" + TypeAliasEntity currentTypeEntity = new TypeAliasEntity(aliasName, this.latestValidContainer(), + idGenerator.generateId(),originalName ); + entityRepo.add(currentTypeEntity); + return ; + } + + public FunctionEntity foundMethodDeclarator(String methodName, String returnType, List throwedType) { + FunctionEntity functionEntity = new FunctionEntity(methodName, this.latestValidContainer(), + idGenerator.generateId(),returnType); + entityRepo.add(functionEntity); + this.typeOrFileContainer().addFunction(functionEntity); + pushToStack(functionEntity); + functionEntity.addThrowTypes(throwedType); + return functionEntity; + } + + + + public void foundNewImport(Import imported) { + currentFileEntity.addImport(imported); + } + + public TypeEntity currentType() { + for (int i = entityStack.size() - 1; i >= 0; i--) { + Entity t = entityStack.get(i); + if (t instanceof TypeEntity) + return (TypeEntity) t; + } + return null; + } + + public ContainerEntity typeOrFileContainer() { + for (int i = entityStack.size() - 1; i >= 0; i--) { + Entity t = entityStack.get(i); + if (t instanceof TypeEntity) + return (ContainerEntity) t; + if (t instanceof FileEntity) { + return (ContainerEntity)t; + } + } + return null; + } + + + public FunctionEntity currentFunction() { + for (int i = entityStack.size() - 1; i >= 0; i--) { + Entity t = entityStack.get(i); + if (t instanceof FunctionEntity) + return (FunctionEntity) t; + } + return null; + } + + public FileEntity currentFile() { + return currentFileEntity; + } + + public Entity latestValidContainer() { + for (int i = entityStack.size() - 1; i >= 0; i--) { + Entity t = entityStack.get(i); + if (t instanceof FunctionEntity) + return t; + if (t instanceof TypeEntity) + return t; + if (t instanceof FileEntity) + return t; + } + return null; + } + + public ContainerEntity lastContainer() { + for (int i = entityStack.size() - 1; i >= 0; i--) { + Entity t = entityStack.get(i); + if (t instanceof ContainerEntity) + return (ContainerEntity) t; + } + return null; + } + + public void foundAnnotation(String name) { + lastContainer().addAnnotation(name); + } + + public void foundImplements(String typeName) { + currentType().addImplements(typeName); + } + + public void foundExtends(String typeName) { + if (currentType()==null) { + System.out.println("error: type do not exist"); + } + currentType().addExtends(typeName); + } + + + public void foundTypeParametes(String typeName) { + lastContainer().addTypeParameter(typeName); + } + + + public void foundVarDefinition(List varNames, String type) { + for (String varName : varNames) { + foundVarDefintion(varName,type); + } + } + + + public void foundVarDefintion(String varName, String type) { + VarEntity var = new VarEntity(varName, type, lastContainer(), idGenerator.generateId()); + lastContainer().addVar(var); + } + + public void foundEnumConstDefinition(String varName) { + String type = lastContainer().getRawName(); + foundVarDefintion(varName,type); + } + + protected Stack entityStack = new Stack(); + + private void pushToStack(Entity entity) { + entityStack.push(entity); + } + + + public void exitLastedEntity() { + entityStack.pop(); + } + +} \ No newline at end of file diff --git a/data/undertestsrc/java/depends/extractor/LangWorkers.java b/data/undertestsrc/java/depends/extractor/LangWorkers.java new file mode 100644 index 0000000..91052d7 --- /dev/null +++ b/data/undertestsrc/java/depends/extractor/LangWorkers.java @@ -0,0 +1,18 @@ +package depends.extractor; + +import java.util.HashMap; + +public class LangWorkers { + private static LangWorkers inst = new LangWorkers(); + public HashMap workers = new HashMap<>(); + public static LangWorkers getRegistry() { + return inst; + } + public AbstractLangWorker getWorkerOf(String lang) { + return workers.get(lang); + } + public void register(AbstractLangWorker worker) { + if (getWorkerOf(worker.supportedLanguage())!=null) return; + workers.put(worker.supportedLanguage(), worker); + } +} diff --git a/data/undertestsrc/java/depends/extractor/cpp/CppBuiltInType.java b/data/undertestsrc/java/depends/extractor/cpp/CppBuiltInType.java new file mode 100644 index 0000000..89669d1 --- /dev/null +++ b/data/undertestsrc/java/depends/extractor/cpp/CppBuiltInType.java @@ -0,0 +1,47 @@ +package depends.extractor.cpp; + +import depends.entity.repo.BuiltInType; + +public class CppBuiltInType extends BuiltInType { + + public CppBuiltInType() { + super.createBuiltInTypes(); + } + + @Override + public String[] getBuiltInTypeStr() { + return new String[] { "alignas", "alignof", "asm", "auto", "bool", "break", "case", "catch", "char", + "char16_t", "char32_t", "class", "const", "constexpr", "const_cast", "continue", "decltype", + "default", "delete", "do", "double", "dynamic_cast", "else", "enum", "explicit", "export", "extern", + "false", "final", "float", "for", "friend", "goto", "if", "inline", "int", "long", "mutable", + "namespace", "new", "noexcept", "nullptr", "operator", "override", "private", "protected", "public", + "register", "reinterpret_cast", "return", "short", "signed", "sizeof", "static", "static_assert", + "static_cast", "struct", "switch", "template", "this", "thread_local", "throw", "true", "try", + "typedef", "typeid", "typename", "union", "unsigned", "using", "virtual", "void", "volatile", + "wchar_t", "while", "", + "__cplusplus","_cpp_aggregate_bases","__cpp_aggregate_nsdmi","__cpp_alias_templates","__cpp_aligned_new", + "__cpp_attributes","__cpp_binary_literals","__cpp_capture_star_this","__cpp_constexpr","__cpp_decltype", + "__cpp_decltype_auto","__cpp_deduction_guides","__cpp_delegating_constructors", + "__cpp_enumerator_attributes","__cpp_explicit_bool","__cpp_fold_expressions","__cpp_generic_lambdas", + "__cpp_guaranteed_copy_elision","__cpp_hex_float","__cpp_if_constexpr","__cpp_inheriting_constructors", + "__cpp_init_captures","__cpp_initializer_lists","__cpp_inline_variables","__cpp_lambdas", + "__cpp_namespace_attributes","__cpp_noexcept_function_type","__cpp_nontype_template_args", + "__cpp_nontype_template_parameter_auto","__cpp_nontype_template_parameter_class","__cpp_nsdmi" + + "","__cpp_range_based_for","__cpp_raw_strings","__cpp_ref_qualifiers","__cpp_return_type_deduction" + ,"__cpp_rvalue_references","__cpp_sized_deallocation","__cpp_static_assert","__cpp_structured_bindings", + "__cpp_template_template_args","__cpp_threadsafe_static_init","__cpp_unicode_characters","__cpp_unicode_literals", + "__cpp_user_defined_literals","__cpp_variable_templates","__cpp_variadic_templates","__cpp_variadic_using", + "__DATE__","__FILE__","__LINE__","__STDC__","__STDC_ANALYZABLE__","__STDC_HOSTED__","__STDC_IEC_559__", + "__STDC_IEC_559_COMPLEX__","__STDC_ISO_10646__","__STDC_LIB_EXT1__","__STDC_MB_MIGHT_NEQ_WC__", + "__STDC_NO_ATOMICS__","__STDC_NO_COMPLEX__","__STDC_NO_THREADS__","__STDC_NO_VLA__", + "__STDCPP_DEFAULT_NEW_ALIGNMENT__","__STDCPP_STRICT_POINTER_SAFETY__","__STDCPP_THREADS__", + "__STDC_UTF_16__","__STDC_UTF_32__","__STDC_VERSION__","__TIME__" + }; + } + + @Override + public String[] getBuiltInPrefixStr() { + return new String[] {"__"}; + } + +} \ No newline at end of file diff --git a/data/undertestsrc/java/depends/extractor/cpp/CppFileParser.java b/data/undertestsrc/java/depends/extractor/cpp/CppFileParser.java new file mode 100644 index 0000000..1768619 --- /dev/null +++ b/data/undertestsrc/java/depends/extractor/cpp/CppFileParser.java @@ -0,0 +1,14 @@ +package depends.extractor.cpp; + +import depends.entity.repo.EntityRepo; +import depends.relations.Inferer; + +public abstract class CppFileParser implements depends.extractor.FileParser { + protected String fileFullPath; + protected EntityRepo entityRepo; + public CppFileParser(String fileFullPath, EntityRepo entityRepo, Inferer inferer) { + this.fileFullPath = fileFullPath; + this.entityRepo = entityRepo; + } + +} diff --git a/data/undertestsrc/java/depends/extractor/cpp/CppImportLookupStrategy.java b/data/undertestsrc/java/depends/extractor/cpp/CppImportLookupStrategy.java new file mode 100644 index 0000000..2ae9ae1 --- /dev/null +++ b/data/undertestsrc/java/depends/extractor/cpp/CppImportLookupStrategy.java @@ -0,0 +1,87 @@ +package depends.extractor.cpp; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; + +import depends.entity.Entity; +import depends.entity.FileEntity; +import depends.entity.repo.EntityRepo; +import depends.importtypes.FileImport; +import depends.importtypes.Import; +import depends.relations.ImportLookupStrategy; +import depends.relations.Inferer; + +public class CppImportLookupStrategy implements ImportLookupStrategy { + @Override + public Entity lookupImportedType(String name, FileEntity fileEntity, EntityRepo repo, Inferer inferer) { + String importedString = fileEntity.importedSuffixMatch(name); + if (importedString!=null) { + Entity r = repo.getEntity(importedString); + if (r!=null) return r; + } + + HashSet fileSet = new HashSet<>(); + foundIncludedFiles(fileSet, fileEntity.getImportedFiles(),repo); + + for (String file:fileSet) { + Entity importedItem = repo.getEntity(file); + if (importedItem instanceof FileEntity) { + FileEntity importedFile = (FileEntity) repo.getEntity(file); + if (importedFile==null) continue; + Entity entity = inferer.resolveName(importedFile,name, false); + if (entity!=null) return entity; + List namespaces = fileEntity.getImportedTypes(); + for (Entity ns:namespaces) { + String nameWithPrefix = ns.getQualifiedName() + "." + name; + entity = inferer.resolveName(importedFile,nameWithPrefix, false); + if (entity!=null) return entity; + } + } + } + return null; + } + + private void foundIncludedFiles(HashSet fileSet, List importedFiles, EntityRepo repo) { + for (Entity file:importedFiles) { + if (file==null ) continue; + if (!(file instanceof FileEntity)) continue; + if (fileSet.contains(file.getRawName())) continue; + fileSet.add(file.getRawName()); + foundIncludedFiles(fileSet,((FileEntity)file).getImportedFiles(),repo); + } + } + + + @Override + public List getImportedRelationEntities(List importedList, EntityRepo repo) { + ArrayList result = new ArrayList<>(); + for (Import importedItem:importedList) { + if (importedItem instanceof FileImport) { + Entity imported = repo.getEntity(importedItem.getContent()); + if (imported==null) continue; + result.add(imported); + } + } + return result; + } + + @Override + public List getImportedTypes(List importedList, EntityRepo repo) { + ArrayList result = new ArrayList<>(); + for (Import importedItem:importedList) { + if (!(importedItem instanceof FileImport)) { + Entity imported = repo.getEntity(importedItem.getContent()); + if (imported==null) continue; + result.add(imported); + } + } + return result; + } + + @Override + public List getImportedFiles(List importedList, EntityRepo repo) { + return getImportedRelationEntities(importedList,repo); + } + +} diff --git a/data/undertestsrc/java/depends/extractor/cpp/CppWorker.java b/data/undertestsrc/java/depends/extractor/cpp/CppWorker.java new file mode 100644 index 0000000..d2d3df1 --- /dev/null +++ b/data/undertestsrc/java/depends/extractor/cpp/CppWorker.java @@ -0,0 +1,43 @@ +package depends.extractor.cpp; + +import java.util.ArrayList; +import java.util.List; + +import depends.extractor.AbstractLangWorker; +import depends.extractor.FileParser; +import depends.extractor.cpp.cdt.CdtCppFileParser; +import depends.extractor.cpp.cdt.PreprocessorHandler; +import depends.relations.Inferer; + +public class CppWorker extends AbstractLangWorker { + private static final String LANG = "cpp"; + private static final String[] SUFFIX = new String[] {".cpp",".cc",".c",".h",".hpp",".hh"}; + PreprocessorHandler preprocessorHandler; + public CppWorker(String inputDir, String[] includeDir) { + super(inputDir,includeDir); + preprocessorHandler = new PreprocessorHandler(super.includePaths()); + inferer = new Inferer(entityRepo,new CppImportLookupStrategy(),new CppBuiltInType()); + } + + + @Override + public String supportedLanguage() { + return LANG; + } + + @Override + public String[] fileSuffixes() { + return SUFFIX; + } + + + @Override + protected FileParser getFileParser(String fileFullPath) { + return new CdtCppFileParser(fileFullPath,entityRepo,preprocessorHandler,inferer); + //return new Antlr4CppFileParser(fileFullPath,entityRepo,super.includePaths()); + } + + public List getErrors(){ + return new ArrayList(preprocessorHandler.getNotExistedIncludedFiles()); + } +} diff --git a/data/undertestsrc/java/depends/extractor/cpp/cdt/ANSICParserExtensionConfigurationExtension.java b/data/undertestsrc/java/depends/extractor/cpp/cdt/ANSICParserExtensionConfigurationExtension.java new file mode 100644 index 0000000..0cee4f7 --- /dev/null +++ b/data/undertestsrc/java/depends/extractor/cpp/cdt/ANSICParserExtensionConfigurationExtension.java @@ -0,0 +1,22 @@ +package depends.extractor.cpp.cdt; + +import org.eclipse.cdt.core.dom.parser.c.ANSICParserExtensionConfiguration; + +class ANSICParserExtensionConfigurationExtension extends ANSICParserExtensionConfiguration { + + @Override + public boolean supportDeclspecSpecifiers() { + return false; + } + + @Override + public boolean supportKnRC() { + return false; + } + + @Override + public boolean supportStatementsInExpressions() { + return false; + } + +} diff --git a/data/undertestsrc/java/depends/extractor/cpp/cdt/ASTStringUtil.java b/data/undertestsrc/java/depends/extractor/cpp/cdt/ASTStringUtil.java new file mode 100644 index 0000000..380a374 --- /dev/null +++ b/data/undertestsrc/java/depends/extractor/cpp/cdt/ASTStringUtil.java @@ -0,0 +1,1222 @@ +package depends.extractor.cpp.cdt; + +import org.eclipse.cdt.core.dom.ast.IASTArrayDeclarator; +import org.eclipse.cdt.core.dom.ast.IASTArrayModifier; +import org.eclipse.cdt.core.dom.ast.IASTArraySubscriptExpression; +import org.eclipse.cdt.core.dom.ast.IASTBinaryExpression; +import org.eclipse.cdt.core.dom.ast.IASTCastExpression; +import org.eclipse.cdt.core.dom.ast.IASTCompositeTypeSpecifier; +import org.eclipse.cdt.core.dom.ast.IASTConditionalExpression; +import org.eclipse.cdt.core.dom.ast.IASTDeclSpecifier; +import org.eclipse.cdt.core.dom.ast.IASTDeclarator; +import org.eclipse.cdt.core.dom.ast.IASTElaboratedTypeSpecifier; +import org.eclipse.cdt.core.dom.ast.IASTEnumerationSpecifier; +import org.eclipse.cdt.core.dom.ast.IASTEqualsInitializer; +import org.eclipse.cdt.core.dom.ast.IASTExpression; +import org.eclipse.cdt.core.dom.ast.IASTExpressionList; +import org.eclipse.cdt.core.dom.ast.IASTFieldDeclarator; +import org.eclipse.cdt.core.dom.ast.IASTFieldReference; +import org.eclipse.cdt.core.dom.ast.IASTFunctionCallExpression; +import org.eclipse.cdt.core.dom.ast.IASTFunctionDeclarator; +import org.eclipse.cdt.core.dom.ast.IASTFunctionDefinition; +import org.eclipse.cdt.core.dom.ast.IASTIdExpression; +import org.eclipse.cdt.core.dom.ast.IASTInitializer; +import org.eclipse.cdt.core.dom.ast.IASTInitializerClause; +import org.eclipse.cdt.core.dom.ast.IASTInitializerList; +import org.eclipse.cdt.core.dom.ast.IASTLiteralExpression; +import org.eclipse.cdt.core.dom.ast.IASTName; +import org.eclipse.cdt.core.dom.ast.IASTNamedTypeSpecifier; +import org.eclipse.cdt.core.dom.ast.IASTNode; +import org.eclipse.cdt.core.dom.ast.IASTParameterDeclaration; +import org.eclipse.cdt.core.dom.ast.IASTPointer; +import org.eclipse.cdt.core.dom.ast.IASTPointerOperator; +import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclSpecifier; +import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclaration; +import org.eclipse.cdt.core.dom.ast.IASTStandardFunctionDeclarator; +import org.eclipse.cdt.core.dom.ast.IASTTypeId; +import org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression; +import org.eclipse.cdt.core.dom.ast.IASTUnaryExpression; +import org.eclipse.cdt.core.dom.ast.c.ICASTDesignatedInitializer; +import org.eclipse.cdt.core.dom.ast.c.ICASTSimpleDeclSpecifier; +import org.eclipse.cdt.core.dom.ast.c.ICASTTypeIdInitializerExpression; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCastExpression; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTConstructorInitializer; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTDeclarator; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTDecltypeSpecifier; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTDeleteExpression; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTDesignatedInitializer; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTElaboratedTypeSpecifier; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionDeclarator; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionDeclarator.RefQualifier; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNameSpecifier; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNewExpression; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTPackExpansionExpression; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTParameterDeclaration; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTPointerToMember; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTQualifiedName; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTReferenceOperator; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTSimpleTypeConstructorExpression; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTSimpleTypeTemplateParameter; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateId; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateParameter; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplatedTypeTemplateParameter; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTypeId; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTypeIdExpression; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTUnaryExpression; +import org.eclipse.cdt.core.dom.ast.gnu.IGNUASTCompoundStatementExpression; +import org.eclipse.cdt.core.dom.ast.gnu.c.ICASTKnRFunctionDeclarator; +import org.eclipse.cdt.core.parser.GCCKeywords; +import org.eclipse.cdt.core.parser.Keywords; +import org.eclipse.cdt.core.parser.util.CharArrayUtils; +import org.eclipse.cdt.internal.core.dom.parser.ASTQueries; + +import depends.relations.Inferer; + +/** + * This is a utility class to help convert AST elements to strings. + * + * @see org.eclipse.cdt.core.dom.ast.ASTTypeUtil + */ +public class ASTStringUtil { + private static final String SPACE= " "; //$NON-NLS-1$ + private static final String COMMA_SPACE= ", "; //$NON-NLS-1$ + private static final String[] EMPTY_STRING_ARRAY= {}; + + /** + * Return the qualified name if the given IASTName + * is an ICPPASTQualifiedName, otherwise a simple name is returned. + * + * @param name + * @return a (possibly) qualified name + */ + public static String getQualifiedName(IASTName name) { + return appendQualifiedNameString(new StringBuilder(), name).toString(); + } + + /** + * Return the non-qualified name. + * + * @param name + * @return a non-qualified name + */ + public static String getSimpleName(IASTName name) { + return appendSimpleNameString(new StringBuilder(), name).toString(); + } + + /** + * Compute a signature string with parameters, without initializers. + */ + public static String getSignatureString(IASTDeclarator declarator) { + return trimRight(appendSignatureString(new StringBuilder(), declarator)).toString(); + } + + /** + * Compute a signature string including parameters, but without initializers. + * + * @param declSpecifier + * @param declarator + * @return the signature string + */ + public static String getSignatureString(IASTDeclSpecifier declSpecifier, IASTDeclarator declarator) { + final StringBuilder buffer= new StringBuilder(); + appendDeclarationString(buffer, declSpecifier, declarator, null); + return trimRight(buffer).toString(); + } + + /** + * Compute the return-type string for a function declarator. + * + * @param declSpecifier + * @param fdecl + * @return the return type string + */ + public static String getReturnTypeString(IASTDeclSpecifier declSpecifier, IASTFunctionDeclarator fdecl) { + final StringBuilder buffer= new StringBuilder(); + final IASTDeclarator declarator= ASTQueries.findOutermostDeclarator(fdecl); + appendDeclarationString(buffer, declSpecifier, declarator, fdecl); + return trimRight(buffer).toString(); + } + + /** + * Get the signatures of the function parameter declarations. + * + * @param functionDeclarator + * @return the parameter signature array + */ + public static String[] getParameterSignatureArray(IASTFunctionDeclarator functionDeclarator) { + if (functionDeclarator instanceof IASTStandardFunctionDeclarator) { + final IASTStandardFunctionDeclarator standardFunctionDecl= (IASTStandardFunctionDeclarator) functionDeclarator; + final IASTParameterDeclaration[] parameters= standardFunctionDecl.getParameters(); + final boolean takesVarArgs= standardFunctionDecl.takesVarArgs(); + final String[] parameterStrings= new String[parameters.length + (takesVarArgs ? 1 : 0)]; + int i; + for (i = 0; i < parameters.length; ++i) { + parameterStrings[i]= getParameterSignatureString(parameters[i]); + } + if (takesVarArgs) { + parameterStrings[i]= new String(Keywords.cpELLIPSIS); + } + return parameterStrings; + } else if (functionDeclarator instanceof ICASTKnRFunctionDeclarator) { + final ICASTKnRFunctionDeclarator knrDeclarator= (ICASTKnRFunctionDeclarator) functionDeclarator; + final IASTName[] names= knrDeclarator.getParameterNames(); + final String[] result= new String[names.length]; + for (int i = 0; i < names.length; i++) { + if (names[i] != null) { + final IASTDeclarator declaratorForParameterName= knrDeclarator.getDeclaratorForParameterName(names[i]); + if (declaratorForParameterName != null) { + result[i]= getSignatureString(declaratorForParameterName); + } else { + result[i]= "?"; //$NON-NLS-1$ + } + } + } + return result; + } + return EMPTY_STRING_ARRAY; + } + + /** + * Convert the given template parameters into a string array. + * + * @param templateParams + * @return a string array of template parameters + */ + public static String[] getTemplateParameterArray(ICPPASTTemplateParameter[] templateParams) { + final String[] parameterTypes= new String[templateParams.length]; + for (int i = 0; i < templateParams.length; i++) { + final StringBuilder paramType= new StringBuilder(); + final ICPPASTTemplateParameter parameter= templateParams[i]; + appendTemplateParameterString(paramType, parameter); + parameterTypes[i]= trimRight(paramType).toString(); + } + return parameterTypes; + } + + /** + * Returns a string representation for the given expression + */ + public static String getExpressionString(IASTExpression expression) { + StringBuilder buf= new StringBuilder(); + return appendExpressionString(buf, expression).toString(); + } + + public static String getInitializerString(IASTInitializer init) { + StringBuilder buf= new StringBuilder(); + return appendInitializerString(buf, init).toString(); + } + + /** + * Joins strings together using a given delimiter. + * @param strings the strings to join. + * @param delimiter the delimiter that is put between the strings when joining them. + * @return the joined string. + */ + public static String join(String[] strings, CharSequence delimiter) { + if (strings.length == 0) { + return ""; //$NON-NLS-1$ + } else if (strings.length == 1) { + return strings[0]; + } else { + StringBuilder buf = new StringBuilder(strings[0]); + for (int i = 1; i < strings.length; i++) { + buf.append(delimiter); + buf.append(strings[i]); + } + return buf.toString(); + } + } + + private static String getParameterSignatureString(IASTParameterDeclaration parameterDeclaration) { + return trimRight(appendParameterDeclarationString(new StringBuilder(), parameterDeclaration)).toString(); + } + + public static StringBuilder appendSignatureString(StringBuilder buffer, IASTDeclarator declarator) { + // get the declaration node + IASTNode node= declarator.getParent(); + while (node instanceof IASTDeclarator) { + declarator= (IASTDeclarator) node; + node= node.getParent(); + } + + // get the declSpec + final IASTDeclSpecifier declSpec; + if (node instanceof IASTParameterDeclaration) { + declSpec= ((IASTParameterDeclaration) node).getDeclSpecifier(); + } else if (node instanceof IASTSimpleDeclaration) { + declSpec= ((IASTSimpleDeclaration) node).getDeclSpecifier(); + } else if (node instanceof IASTFunctionDefinition) { + declSpec= ((IASTFunctionDefinition) node).getDeclSpecifier(); + } else if (node instanceof IASTTypeId) { + declSpec= ((IASTTypeId) node).getDeclSpecifier(); + } else { + declSpec= null; + } + + return appendDeclarationString(buffer, declSpec, declarator, null); + } + + private static StringBuilder appendDeclarationString(StringBuilder buffer, IASTDeclSpecifier declSpecifier, + IASTDeclarator declarator, IASTFunctionDeclarator returnTypeOf) { + if (declSpecifier != null) { + appendDeclSpecifierString(buffer, declSpecifier); + trimRight(buffer); + } + appendDeclaratorString(buffer, declarator, false, returnTypeOf); + return buffer; + } + + private static StringBuilder appendDeclaratorString(StringBuilder buffer, IASTDeclarator declarator, + boolean protectPointers, IASTFunctionDeclarator returnTypeOf) { + if (declarator == null) { + return buffer; + } + final IASTPointerOperator[] ptrs = declarator.getPointerOperators(); + final boolean useParenthesis= protectPointers && ptrs.length > 0; + if (useParenthesis) { + buffer.append(Keywords.cpLPAREN); + protectPointers= false; + } + + appendPointerOperatorsString(buffer, ptrs); + + if (declarator != returnTypeOf) { + final IASTDeclarator nestedDeclarator= declarator.getNestedDeclarator(); + if (nestedDeclarator != null) { + protectPointers= + protectPointers || declarator instanceof IASTArrayDeclarator + || declarator instanceof IASTFunctionDeclarator + || declarator instanceof IASTFieldDeclarator; + appendDeclaratorString(buffer, nestedDeclarator, protectPointers, returnTypeOf); + } else if (declarator instanceof ICPPASTDeclarator && ((ICPPASTDeclarator) declarator).declaresParameterPack()) { + buffer.append(Keywords.cpELLIPSIS); + } + + if (declarator instanceof IASTArrayDeclarator) { + appendArrayQualifiersString(buffer, (IASTArrayDeclarator) declarator); + } else if (declarator instanceof IASTFunctionDeclarator) { + final IASTFunctionDeclarator functionDecl= (IASTFunctionDeclarator) declarator; + appendParameterSignatureString(buffer, functionDecl); + if (declarator instanceof ICPPASTFunctionDeclarator) { + final ICPPASTFunctionDeclarator cppFunctionDecl= (ICPPASTFunctionDeclarator) declarator; + if (cppFunctionDecl.isConst()) { + buffer.append(Keywords.CONST).append(' '); + } + if (cppFunctionDecl.isVolatile()) { + buffer.append(Keywords.VOLATILE).append(' '); + } + RefQualifier refQualifier = cppFunctionDecl.getRefQualifier(); + if (refQualifier != null) { + switch (refQualifier) { + case LVALUE: + buffer.append(Keywords.cpAMPER).append(' '); + break; + case RVALUE: + buffer.append(Keywords.cpAND).append(' '); + break; + } + } + if (cppFunctionDecl.isPureVirtual()) { + buffer.append("=0 "); //$NON-NLS-1$ + } + final IASTTypeId[] exceptionTypeIds= cppFunctionDecl.getExceptionSpecification(); + if (exceptionTypeIds != ICPPASTFunctionDeclarator.NO_EXCEPTION_SPECIFICATION) { + buffer.append(Keywords.THROW).append(" ("); //$NON-NLS-1$ + for (int i= 0; i < exceptionTypeIds.length; i++) { + if (i > 0) { + buffer.append(COMMA_SPACE); + } + appendTypeIdString(buffer, exceptionTypeIds[i]); + } + buffer.append(')'); + } + } + } else if (declarator instanceof IASTFieldDeclarator) { + final IASTFieldDeclarator fieldDeclarator= (IASTFieldDeclarator) declarator; + final IASTExpression bitFieldSize= fieldDeclarator.getBitFieldSize(); + if (bitFieldSize != null) { + buffer.append(Keywords.cpCOLON); + appendExpressionString(buffer, bitFieldSize); + } + } else { + // just a nested name + } + } + if (useParenthesis) { + trimRight(buffer); + buffer.append(Keywords.cpRPAREN); + } + return buffer; + } + + private static StringBuilder appendInitializerString(StringBuilder buffer, IASTInitializer initializer) { + if (initializer instanceof IASTEqualsInitializer) { + final IASTEqualsInitializer initializerExpression= (IASTEqualsInitializer) initializer; + buffer.append(Keywords.cpASSIGN); + appendInitClauseString(buffer, initializerExpression.getInitializerClause()); + } else if (initializer instanceof IASTInitializerList) { + final IASTInitializerList initializerList= (IASTInitializerList) initializer; + final IASTInitializerClause[] initializers= initializerList.getClauses(); + buffer.append(Keywords.cpASSIGN); + buffer.append(Keywords.cpLBRACE); + for (int i= 0; i < initializers.length; i++) { + if (i > 0) { + buffer.append(COMMA_SPACE); + } + appendInitClauseString(buffer, initializers[i]); + } + trimRight(buffer); + buffer.append(Keywords.cpRBRACE); + } else if (initializer instanceof ICASTDesignatedInitializer || initializer instanceof ICPPASTDesignatedInitializer) { + //TODO handle ICASTDesignatedInitializer? +// final ICASTDesignatedInitializer designatedInitializer= (ICASTDesignatedInitializer) initializer; +// final ICASTDesignator[] designator= designatedInitializer.getDesignators(); + } else if (initializer instanceof ICPPASTConstructorInitializer) { + final ICPPASTConstructorInitializer constructorInitializer= (ICPPASTConstructorInitializer) initializer; + final IASTInitializerClause[] clauses= constructorInitializer.getArguments(); + buffer.append(Keywords.cpLPAREN); + for (int i= 0; i < clauses.length; i++) { + if (i > 0) { + buffer.append(COMMA_SPACE); + } + appendInitClauseString(buffer, clauses[i]); + } + trimRight(buffer); + buffer.append(Keywords.cpRPAREN); + } else if (initializer != null) { + assert false : "TODO: handle "+ initializer.getClass().getName(); //$NON-NLS-1$ + } + return buffer; + } + + private static StringBuilder appendInitClauseString(StringBuilder buffer, IASTInitializerClause initializerClause) { + if (initializerClause instanceof IASTExpression) { + return appendExpressionString(buffer, (IASTExpression) initializerClause); + } + if (initializerClause instanceof IASTInitializer) { + return appendInitializerString(buffer, (IASTInitializer) initializerClause); + } + return buffer; + } + public static String getTypeIdString(IASTTypeId typeId) { + StringBuilder sb = new StringBuilder(); + return appendBareTypeIdString(sb,typeId).toString(); + } + private static StringBuilder appendBareTypeIdString(StringBuilder buffer, IASTTypeId typeId) { + return appendBareDeclSpecifierString(buffer, typeId.getDeclSpecifier()); + } + + private static StringBuilder appendBareDeclSpecifierString(StringBuilder buffer, IASTDeclSpecifier declSpecifier) { + if (declSpecifier instanceof IASTCompositeTypeSpecifier) { + final IASTCompositeTypeSpecifier compositeTypeSpec= (IASTCompositeTypeSpecifier) declSpecifier; + appendBareNameString(buffer, compositeTypeSpec.getName()); + } else if (declSpecifier instanceof IASTElaboratedTypeSpecifier) { + final IASTElaboratedTypeSpecifier elaboratedTypeSpec= (IASTElaboratedTypeSpecifier) declSpecifier; + appendBareNameString(buffer, elaboratedTypeSpec.getName()); + } else if (declSpecifier instanceof IASTEnumerationSpecifier) { + final IASTEnumerationSpecifier enumerationSpec= (IASTEnumerationSpecifier) declSpecifier; + appendBareNameString(buffer, enumerationSpec.getName()); + } else if (declSpecifier instanceof IASTSimpleDeclSpecifier) { + buffer.append(Inferer.buildInType.getRawName()); + } else if (declSpecifier instanceof IASTNamedTypeSpecifier) { + final IASTNamedTypeSpecifier namedTypeSpec= (IASTNamedTypeSpecifier) declSpecifier; + appendBareNameString(buffer, namedTypeSpec.getName()); + } + return buffer; + } + + private static StringBuilder appendTypeIdString(StringBuilder buffer, IASTTypeId typeId) { + appendDeclSpecifierString(buffer, typeId.getDeclSpecifier()); + appendDeclaratorString(buffer, typeId.getAbstractDeclarator(), false, null); + if (typeId instanceof ICPPASTTypeId && ((ICPPASTTypeId) typeId).isPackExpansion()) + buffer.append(Keywords.cpELLIPSIS); + return buffer; + } + + private static StringBuilder trimRight(StringBuilder buffer) { + int length= buffer.length(); + while (length > 0 && buffer.charAt(length - 1) == ' ') { + --length; + } + buffer.setLength(length); + return buffer; + } + + private static StringBuilder appendArrayQualifiersString(StringBuilder buffer, IASTArrayDeclarator declarator) { + final IASTArrayModifier[] modifiers= declarator.getArrayModifiers(); + final int count= modifiers.length; + for (int i = 0; i < count; i++) { + buffer.append(Keywords.cpLBRACKET).append(Keywords.cpRBRACKET); + } + return buffer; + } + + private static StringBuilder appendPointerOperatorsString(StringBuilder buffer, IASTPointerOperator[] pointerOperators) { + for (final IASTPointerOperator pointerOperator : pointerOperators) { + if (pointerOperator instanceof IASTPointer) { + final IASTPointer pointer= (IASTPointer) pointerOperator; + if (pointer instanceof ICPPASTPointerToMember) { + final ICPPASTPointerToMember pointerToMember= (ICPPASTPointerToMember) pointer; + appendQualifiedNameString(buffer, pointerToMember.getName()); + } + buffer.append(Keywords.cpSTAR); + if (pointer.isConst()) { + buffer.append(' ').append(Keywords.CONST); + } + if (pointer.isVolatile()) { + buffer.append(' ').append(Keywords.VOLATILE); + } + if (pointer.isRestrict()) { + buffer.append(' ').append(Keywords.RESTRICT); + } + } else if (pointerOperator instanceof ICPPASTReferenceOperator) { + if (((ICPPASTReferenceOperator) pointerOperator).isRValueReference()) { + buffer.append(Keywords.cpAND); + } else { + buffer.append(Keywords.cpAMPER); + } + } + } + return buffer; + } + + private static StringBuilder appendParameterSignatureString(StringBuilder buffer, IASTFunctionDeclarator functionDeclarator) { + if (functionDeclarator instanceof IASTStandardFunctionDeclarator) { + final IASTStandardFunctionDeclarator standardFunctionDecl= (IASTStandardFunctionDeclarator) functionDeclarator; + final IASTParameterDeclaration[] parameters= standardFunctionDecl.getParameters(); + final boolean takesVarArgs= standardFunctionDecl.takesVarArgs(); + buffer.append(Keywords.cpLPAREN); + for (int i = 0; i < parameters.length; i++) { + if (i > 0) { + buffer.append(COMMA_SPACE); + } + appendParameterDeclarationString(buffer, parameters[i]); + } + if (takesVarArgs) { + if (parameters.length > 0) { + buffer.append(COMMA_SPACE); + } + buffer.append(Keywords.cpELLIPSIS); + } + trimRight(buffer); + buffer.append(Keywords.cpRPAREN); + } else if (functionDeclarator instanceof ICASTKnRFunctionDeclarator) { + buffer.append(Keywords.cpLPAREN); + final ICASTKnRFunctionDeclarator knrDeclarator= (ICASTKnRFunctionDeclarator) functionDeclarator; + final IASTName[] names= knrDeclarator.getParameterNames(); + for (int i = 0; i < names.length; i++) { + if (i > 0) { + buffer.append(COMMA_SPACE); + } + if (names[i] != null) { + final IASTDeclarator declaratorForParameterName= knrDeclarator.getDeclaratorForParameterName(names[i]); + if (declaratorForParameterName != null) { + appendSignatureString(buffer, declaratorForParameterName); + } + } + } + trimRight(buffer); + buffer.append(Keywords.cpRPAREN); + } + return buffer; + } + + private static StringBuilder appendParameterDeclarationString(StringBuilder buffer, IASTParameterDeclaration parameter) { + final IASTDeclSpecifier declSpecifier= parameter.getDeclSpecifier(); + if (declSpecifier != null) { + appendDeclSpecifierString(buffer, declSpecifier); + trimRight(buffer); + } + final IASTDeclarator declarator= parameter.getDeclarator(); + if (declarator != null) { + appendDeclaratorString(buffer, declarator, false, null); + appendInitializerString(buffer, declarator.getInitializer()); + } + return buffer; + } + + public static StringBuilder appendDeclSpecifierString(StringBuilder buffer, IASTDeclSpecifier declSpecifier) { + if (declSpecifier.isConst()) { + buffer.append(Keywords.CONST).append(' '); + } + if (declSpecifier.isVolatile()) { + buffer.append(Keywords.VOLATILE).append(' '); + } + +// buffer.append(Keywords.TYPEDEF).append(' '); +// break) +// if (declSpecifier.isInline()) { +// buffer.append(Keywords.INLINE).append(' '); +// } +// if (declSpecifier instanceof ICASTDeclSpecifier) { +// final ICASTDeclSpecifier cDeclSpec= (ICASTDeclSpecifier) declSpecifier; +// if (cDeclSpec.isRestrict()) { +// buffer.append(Keywords.RESTRICT).append(' '); +// } +// } else if (declSpecifier instanceof ICPPASTDeclSpecifier) { +// final ICPPASTDeclSpecifier cppDeclSpec= (ICPPASTDeclSpecifier) declSpecifier; +// if (cppDeclSpec.isFriend()) { +// buffer.append(Keywords.FRIEND).append(' '); +// } +// if (cppDeclSpec.isVirtual()) { +// buffer.append(Keywords.VIRTUAL).append(' '); +// } +// if (cppDeclSpec.isExplicit()) { +// buffer.append(Keywords.EXPLICIT).append(' '); +// } +// if (declSpecifier instanceof IGPPASTDeclSpecifier) { +// final IGPPASTDeclSpecifier gppDeclSpec= (IGPPASTDeclSpecifier) declSpecifier; +// if (gppDeclSpec.isRestrict()) { +// buffer.append(Keywords.RESTRICT).append(' '); +// } +// } +// } + // storage class +// final int storageClass= declSpecifier.getStorageClass(); +// switch (storageClass) { +// case IASTDeclSpecifier.sc_typedef: +// buffer.append(Keywords.TYPEDEF).append(' '); +// break; +// case IASTDeclSpecifier.sc_extern: +// buffer.append(Keywords.EXTERN).append(' '); +// break; +// case IASTDeclSpecifier.sc_static: +// buffer.append(Keywords.STATIC).append(' '); +// break; +// case IASTDeclSpecifier.sc_auto: +// buffer.append(Keywords.AUTO).append(' '); +// break; +// case IASTDeclSpecifier.sc_register: +// buffer.append(Keywords.REGISTER).append(' '); +// break; +// case ICPPASTDeclSpecifier.sc_mutable: +// buffer.append(Keywords.MUTABLE).append(' '); +// break; +// } + if (declSpecifier instanceof IASTCompositeTypeSpecifier) { + final IASTCompositeTypeSpecifier compositeTypeSpec= (IASTCompositeTypeSpecifier) declSpecifier; + final int key= compositeTypeSpec.getKey(); + switch (key) { + case IASTCompositeTypeSpecifier.k_struct: + buffer.append(Keywords.STRUCT).append(' '); + break; + case IASTCompositeTypeSpecifier.k_union: + buffer.append(Keywords.UNION).append(' '); + break; + case ICPPASTCompositeTypeSpecifier.k_class: + buffer.append(Keywords.CLASS).append(' '); + break; + default: + } + appendQualifiedNameString(buffer, compositeTypeSpec.getName()); + } else if (declSpecifier instanceof IASTElaboratedTypeSpecifier) { + final IASTElaboratedTypeSpecifier elaboratedTypeSpec= (IASTElaboratedTypeSpecifier) declSpecifier; + switch (elaboratedTypeSpec.getKind()) { + case IASTElaboratedTypeSpecifier.k_enum: + buffer.append(Keywords.ENUM).append(' '); + break; + case IASTElaboratedTypeSpecifier.k_struct: + buffer.append(Keywords.STRUCT).append(' '); + break; + case IASTElaboratedTypeSpecifier.k_union: + buffer.append(Keywords.UNION).append(' '); + break; + case ICPPASTElaboratedTypeSpecifier.k_class: + buffer.append(Keywords.CLASS).append(' '); + break; + default: + assert false; + } + appendQualifiedNameString(buffer, elaboratedTypeSpec.getName()); + } else if (declSpecifier instanceof IASTEnumerationSpecifier) { + final IASTEnumerationSpecifier enumerationSpec= (IASTEnumerationSpecifier) declSpecifier; + buffer.append(Keywords.ENUM).append(' '); + appendQualifiedNameString(buffer, enumerationSpec.getName()); + } else if (declSpecifier instanceof IASTSimpleDeclSpecifier) { + final IASTSimpleDeclSpecifier simpleDeclSpec= (IASTSimpleDeclSpecifier) declSpecifier; + if (simpleDeclSpec.isSigned()) { + buffer.append(Keywords.SIGNED).append(' '); + } + if (simpleDeclSpec.isUnsigned()) { + buffer.append(Keywords.UNSIGNED).append(' '); + } + if (simpleDeclSpec.isShort()) { + buffer.append(Keywords.SHORT).append(' '); + } + if (simpleDeclSpec.isLong()) { + buffer.append(Keywords.LONG).append(' '); + } + if (simpleDeclSpec.isLongLong()) { + buffer.append(Keywords.LONG_LONG).append(' '); + } + if (simpleDeclSpec.isComplex()) { + buffer.append(Keywords._COMPLEX).append(' '); + } + if (simpleDeclSpec.isImaginary()) { + buffer.append(Keywords._IMAGINARY).append(' '); + } + switch (simpleDeclSpec.getType()) { + case IASTSimpleDeclSpecifier.t_void: + buffer.append(Keywords.VOID).append(' '); + break; + case IASTSimpleDeclSpecifier.t_char: + buffer.append(Keywords.CHAR).append(' '); + break; + case IASTSimpleDeclSpecifier.t_int: + buffer.append(Keywords.INT).append(' '); + break; + case IASTSimpleDeclSpecifier.t_int128: + buffer.append(GCCKeywords.cp__int128).append(' '); + break; + case IASTSimpleDeclSpecifier.t_float: + buffer.append(Keywords.FLOAT).append(' '); + break; + case IASTSimpleDeclSpecifier.t_double: + buffer.append(Keywords.DOUBLE).append(' '); + break; + case IASTSimpleDeclSpecifier.t_float128: + buffer.append(GCCKeywords.cp__float128).append(' '); + break; + case IASTSimpleDeclSpecifier.t_decimal32: + buffer.append(GCCKeywords.cp_decimal32).append(' '); + break; + case IASTSimpleDeclSpecifier.t_decimal64: + buffer.append(GCCKeywords.cp_decimal64).append(' '); + break; + case IASTSimpleDeclSpecifier.t_decimal128: + buffer.append(GCCKeywords.cp_decimal128).append(' '); + break; + case IASTSimpleDeclSpecifier.t_bool: + if (simpleDeclSpec instanceof ICASTSimpleDeclSpecifier) { + buffer.append(Keywords.cBOOL).append(' '); + } else { + buffer.append(Keywords.BOOL).append(' '); + } + break; + case IASTSimpleDeclSpecifier.t_wchar_t: + buffer.append(Keywords.WCHAR_T).append(' '); + break; + case IASTSimpleDeclSpecifier.t_char16_t: + buffer.append(Keywords.CHAR16_T).append(' '); + break; + case IASTSimpleDeclSpecifier.t_char32_t: + buffer.append(Keywords.CHAR32_T).append(' '); + break; + default: + } + } else if (declSpecifier instanceof IASTNamedTypeSpecifier) { + final IASTNamedTypeSpecifier namedTypeSpec= (IASTNamedTypeSpecifier) declSpecifier; + appendQualifiedNameString(buffer, namedTypeSpec.getName()); + } + return buffer; + } + + private static StringBuilder appendQualifiedNameString(StringBuilder buffer, IASTName name) { + return appendNameString(buffer, name, true); + } + + private static StringBuilder appendDecltypeSpecifier(StringBuilder buffer, ICPPASTDecltypeSpecifier decltypeSpec) { + buffer.append(Keywords.DECLTYPE); + buffer.append(Keywords.cpLPAREN); + appendExpressionString(buffer, decltypeSpec.getDecltypeExpression()); + buffer.append(Keywords.cpRPAREN); + return buffer; + } + + private static StringBuilder appendQualifiedNameString(StringBuilder buffer, ICPPASTNameSpecifier nameSpec) { + if (nameSpec instanceof IASTName) { + appendQualifiedNameString(buffer, (IASTName) nameSpec); + } else if (nameSpec instanceof ICPPASTDecltypeSpecifier) { + appendDecltypeSpecifier(buffer, (ICPPASTDecltypeSpecifier) nameSpec); + } + return buffer; + } + + private static StringBuilder appendSimpleNameString(StringBuilder buffer, IASTName name) { + return appendNameString(buffer, name, false); + } + + private static StringBuilder appendBareNameString(StringBuilder buffer, IASTName name) { + if (name instanceof ICPPASTQualifiedName) { + final ICPPASTQualifiedName qualifiedName= (ICPPASTQualifiedName) name; + final ICPPASTNameSpecifier[] segments= qualifiedName.getAllSegments(); + for (int i = 0; i < segments.length; i++) { + if (i > 0) { + buffer.append("."); + } + appendQualifiedNameString(buffer, segments[i]); + } + } else if (name instanceof ICPPASTTemplateId) { + final ICPPASTTemplateId templateId= (ICPPASTTemplateId) name; + appendQualifiedNameString(buffer, templateId.getTemplateName()); + } else if (name != null) { + buffer.append(name.getSimpleID()); + } + return buffer; + } + + private static StringBuilder appendNameString(StringBuilder buffer, IASTName name, boolean qualified) { + if (name instanceof ICPPASTQualifiedName) { + final ICPPASTQualifiedName qualifiedName= (ICPPASTQualifiedName) name; + if (qualified) { + final ICPPASTNameSpecifier[] segments= qualifiedName.getAllSegments(); + for (int i = 0; i < segments.length; i++) { + if (i > 0) { + buffer.append(Keywords.cpCOLONCOLON); + } + appendQualifiedNameString(buffer, segments[i]); + } + } else { + IASTName lastName = qualifiedName.getLastName(); + appendNameString(buffer, lastName, false); + } + } else if (name instanceof ICPPASTTemplateId) { + final ICPPASTTemplateId templateId= (ICPPASTTemplateId) name; + appendQualifiedNameString(buffer, templateId.getTemplateName()); + final IASTNode[] templateArguments= templateId.getTemplateArguments(); + buffer.append(Keywords.cpLT); + for (int i = 0; i < templateArguments.length; i++) { + if (i > 0) { + buffer.append(Keywords.cpCOMMA); + } + final IASTNode argument= templateArguments[i]; + if (argument instanceof IASTTypeId) { + appendBareTypeIdString(buffer, (IASTTypeId) argument); + } else if (argument instanceof IASTExpression) { + final IASTExpression expression= (IASTExpression) argument; + appendExpressionString(buffer, expression); + } + trimRight(buffer); + } + buffer.append(Keywords.cpGT); + } else if (name != null) { + buffer.append(name.getSimpleID()); + } + return buffer; + } + + private static StringBuilder appendTemplateParameterString(StringBuilder buffer, ICPPASTTemplateParameter parameter) { + if (parameter instanceof ICPPASTParameterDeclaration) { + appendParameterDeclarationString(buffer, (ICPPASTParameterDeclaration) parameter); + } else if (parameter instanceof ICPPASTSimpleTypeTemplateParameter) { + final ICPPASTSimpleTypeTemplateParameter simpletypeParameter= (ICPPASTSimpleTypeTemplateParameter) parameter; + final IASTName name= simpletypeParameter.getName(); + if (name != null) { + appendSimpleNameString(buffer, name); + } else { + final int type= simpletypeParameter.getParameterType(); + switch (type) { + case ICPPASTSimpleTypeTemplateParameter.st_class: + buffer.append(Keywords.CLASS); + break; + case ICPPASTSimpleTypeTemplateParameter.st_typename: + buffer.append(Keywords.TYPENAME); + break; + } + } + } else if (parameter instanceof ICPPASTTemplatedTypeTemplateParameter) { + final ICPPASTTemplatedTypeTemplateParameter templatedTypeParameter= (ICPPASTTemplatedTypeTemplateParameter) parameter; + final ICPPASTTemplateParameter[] subParameters= templatedTypeParameter.getTemplateParameters(); + buffer.append(Keywords.TEMPLATE).append(Keywords.cpLT); + for (int i = 0; i < subParameters.length; i++) { + final ICPPASTTemplateParameter templateParameter= subParameters[i]; + if (i > 0) { + buffer.append(COMMA_SPACE); + } + appendTemplateParameterString(buffer, templateParameter); + } + trimRight(buffer); + buffer.append(Keywords.cpGT); + } + return buffer; + } + + private static StringBuilder appendExpressionString(StringBuilder buffer, IASTExpression expression) { + if (expression instanceof IASTIdExpression) { + final IASTIdExpression idExpression= (IASTIdExpression) expression; + return appendQualifiedNameString(buffer, idExpression.getName()); + } + if (expression instanceof IASTExpressionList) { + final IASTExpressionList expressionList= (IASTExpressionList) expression; + final IASTExpression[] expressions= expressionList.getExpressions(); + for (int i = 0; i < expressions.length; i++) { + if (i > 0) { + buffer.append(COMMA_SPACE); + } + appendExpressionString(buffer, expressions[i]); + } + return buffer; + } + if (expression instanceof ICPPASTSimpleTypeConstructorExpression) { + final ICPPASTSimpleTypeConstructorExpression typeCast= (ICPPASTSimpleTypeConstructorExpression) expression; + appendDeclSpecifierString(buffer, typeCast.getDeclSpecifier()); + trimRight(buffer); + return appendInitializerString(buffer, typeCast.getInitializer()); + } + if (expression instanceof IASTArraySubscriptExpression) + return appendArraySubscriptExpression(buffer, (IASTArraySubscriptExpression) expression); + if (expression instanceof IASTBinaryExpression) + return appendBinaryExpression(buffer, (IASTBinaryExpression) expression); + if (expression instanceof IASTCastExpression) + return appendCastExpression(buffer, (IASTCastExpression) expression); + if (expression instanceof IASTConditionalExpression) + return appendConditionalExpression(buffer, (IASTConditionalExpression) expression); + if (expression instanceof IASTExpressionList) + return appendExpressionList(buffer, (IASTExpressionList) expression); + if (expression instanceof IASTFieldReference) + return appendFieldReference(buffer, (IASTFieldReference) expression); + if (expression instanceof IASTFunctionCallExpression) + return appendFunctionCallExpression(buffer, (IASTFunctionCallExpression) expression); + if (expression instanceof IASTLiteralExpression) + return appendLiteralExpression(buffer, (IASTLiteralExpression) expression); + if (expression instanceof IASTTypeIdExpression) + return appendTypeIdExpression(buffer, (IASTTypeIdExpression) expression); + if (expression instanceof IASTUnaryExpression) + return appendUnaryExpression(buffer, (IASTUnaryExpression) expression); + if (expression instanceof ICASTTypeIdInitializerExpression) + return appendTypeIdInitializerExpression(buffer, (ICASTTypeIdInitializerExpression) expression); + if (expression instanceof ICPPASTDeleteExpression) + return appendDeleteExpression(buffer, (ICPPASTDeleteExpression) expression); + if (expression instanceof ICPPASTNewExpression) + return appendNewExpression(buffer, (ICPPASTNewExpression) expression); + if (expression instanceof IGNUASTCompoundStatementExpression) + return appendCompoundStatementExpression(buffer, (IGNUASTCompoundStatementExpression) expression); + if (expression instanceof ICPPASTPackExpansionExpression) + return appendPackExpansionExpression(buffer, (ICPPASTPackExpansionExpression) expression); + + return buffer; + } + + private static StringBuilder appendArraySubscriptExpression(StringBuilder buffer, IASTArraySubscriptExpression expression) { + appendExpressionString(buffer, expression.getArrayExpression()); + buffer.append(Keywords.cpLBRACKET); + appendInitClauseString(buffer, expression.getArgument()); + return buffer.append(Keywords.cpRBRACKET); + } + + private static StringBuilder appendCastExpression(StringBuilder buffer, IASTCastExpression expression) { + if ((expression.getOperator() == IASTCastExpression.op_cast)) { + buffer.append(Keywords.cpLPAREN); + appendTypeIdString(buffer, expression.getTypeId()); + buffer.append(Keywords.cpRPAREN); + return appendExpressionString(buffer, expression.getOperand()); + } + + buffer.append(getCastOperatorString(expression)); + buffer.append(Keywords.cpLT); + appendTypeIdString(buffer, expression.getTypeId()); + trimRight(buffer); + buffer.append(Keywords.cpGT); + buffer.append(Keywords.cpLPAREN); + appendExpressionString(buffer, expression.getOperand()); + return buffer.append(Keywords.cpRPAREN); + } + + private static StringBuilder appendFieldReference(StringBuilder buffer, IASTFieldReference expression) { + appendExpressionString(buffer, expression.getFieldOwner()); + buffer.append(expression.isPointerDereference() ? Keywords.cpARROW : Keywords.cpDOT); + + return appendNameString(buffer, expression.getFieldName(), true); + } + + private static StringBuilder appendFunctionCallExpression(StringBuilder buffer, IASTFunctionCallExpression expression) { + appendExpressionString(buffer, expression.getFunctionNameExpression()); + buffer.append(Keywords.cpLPAREN); + IASTInitializerClause[] clauses = expression.getArguments(); + for (int i= 0; i < clauses.length; i++) { + if (i > 0) { + buffer.append(COMMA_SPACE); + } + appendInitClauseString(buffer, (clauses[i])); + } + return buffer.append(Keywords.cpRPAREN); + } + + private static StringBuilder appendTypeIdInitializerExpression(StringBuilder buffer, ICASTTypeIdInitializerExpression expression) { + buffer.append(Keywords.cpLPAREN); + appendTypeIdString(buffer, expression.getTypeId()); + buffer.append(Keywords.cpRPAREN); + return appendInitializerString(buffer, expression.getInitializer()); + } + + private static StringBuilder appendDeleteExpression(StringBuilder buffer, ICPPASTDeleteExpression expression) { + buffer.append(Keywords.DELETE); + buffer.append(SPACE); + return appendExpressionString(buffer, expression.getOperand()); + } + + private static StringBuilder appendCompoundStatementExpression(StringBuilder buffer, IGNUASTCompoundStatementExpression expression) { + buffer.append(Keywords.cpLPAREN).append(Keywords.cpLBRACE); + buffer.append(Keywords.cpELLIPSIS); + return buffer.append(Keywords.cpRBRACE).append(Keywords.cpRPAREN); + } + + private static StringBuilder appendTypeIdExpression(StringBuilder buffer, IASTTypeIdExpression expression) { + buffer.append(getTypeIdExpressionOperator(expression)); + buffer.append(Keywords.cpLPAREN); + appendTypeIdString(buffer, expression.getTypeId()); + trimRight(buffer); + return buffer.append(Keywords.cpRPAREN); + } + + private static StringBuilder appendExpressionList(StringBuilder buffer, IASTExpressionList expression) { + IASTExpression[] exps = expression.getExpressions(); + if (exps != null) { + for (int i = 0; i < exps.length; i++) { + if (i > 0) { + buffer.append(COMMA_SPACE); + } + appendExpressionString(buffer, exps[i]); + } + } + return buffer; + } + + private static StringBuilder appendLiteralExpression(StringBuilder buffer, IASTLiteralExpression expression) { + return buffer.append(expression.toString()); + } + + private static StringBuilder appendConditionalExpression(StringBuilder buffer, IASTConditionalExpression expression) { + appendExpressionString(buffer, expression.getLogicalConditionExpression()); + buffer.append(SPACE); + buffer.append(Keywords.cpQUESTION); + buffer.append(SPACE); + appendExpressionString(buffer, expression.getPositiveResultExpression()); + buffer.append(SPACE); + buffer.append(Keywords.cpCOLON); + buffer.append(SPACE); + return appendExpressionString(buffer, expression.getNegativeResultExpression()); + } + + private static StringBuilder appendNewExpression(StringBuilder buffer, ICPPASTNewExpression expression) { + buffer.append(Keywords.NEW); + buffer.append(SPACE); + final IASTInitializerClause[] args = expression.getPlacementArguments(); + if (args != null) { + buffer.append(Keywords.cpLPAREN); + for (int i = 0; i < args.length; i++) { + if (i != 0) { + buffer.append(COMMA_SPACE); + } + appendInitClauseString(buffer, args[i]); + } + buffer.append(Keywords.cpRPAREN); + } + appendTypeIdString(buffer, expression.getTypeId()); + return appendInitializerString(buffer, expression.getInitializer()); + } + + private static StringBuilder appendBinaryExpression(StringBuilder buffer, IASTBinaryExpression expression) { + appendExpressionString(buffer, expression.getOperand1()); + buffer.append(SPACE); + buffer.append(getBinaryOperatorString(expression)); + buffer.append(SPACE); + return appendExpressionString(buffer, expression.getOperand2()); + } + + private static StringBuilder appendUnaryExpression(StringBuilder buffer, IASTUnaryExpression expression) { + boolean postOperator = false; + boolean primaryBracketed = false; + + switch (expression.getOperator()) { + case IASTUnaryExpression.op_postFixDecr: + case IASTUnaryExpression.op_postFixIncr: + postOperator = true; + break; + case IASTUnaryExpression.op_bracketedPrimary: + primaryBracketed = true; + break; + default: + postOperator = false; + break; + } + + if (!postOperator && !primaryBracketed) + buffer.append(getUnaryOperatorString(expression)); + + // Need to add a space to the unary expression if it is a specific operator. + switch (expression.getOperator()) { + case IASTUnaryExpression.op_sizeof: + case ICPPASTUnaryExpression.op_noexcept: + case ICPPASTUnaryExpression.op_throw: + case ICPPASTUnaryExpression.op_typeid: + buffer.append(SPACE); + break; + } + + if (primaryBracketed) + buffer.append(Keywords.cpLPAREN); + buffer.append(getExpressionString(expression.getOperand())); + if (primaryBracketed) + buffer.append(Keywords.cpRPAREN); + if (postOperator && !primaryBracketed) + buffer.append(getUnaryOperatorString(expression)); + + return buffer; + } + + public static String getCastOperatorString(IASTCastExpression expression) { + int op = expression.getOperator(); + switch (op) { + case ICPPASTCastExpression.op_const_cast: + return Keywords.CONST_CAST; + case ICPPASTCastExpression.op_dynamic_cast: + return Keywords.DYNAMIC_CAST; + case ICPPASTCastExpression.op_reinterpret_cast: + return Keywords.REINTERPRET_CAST; + case ICPPASTCastExpression.op_static_cast: + return Keywords.STATIC_CAST; + } + return ""; //$NON-NLS-1$ + } + + /** + * Returns the String representation of the IASTUnaryExpression's operator. + * + * @param ue + * @return the String representation of the IASTUnaryExpression's operator + */ + public static char[] getUnaryOperatorString(IASTUnaryExpression ue) { + int op = ue.getOperator(); + switch (op) { + case IASTUnaryExpression.op_noexcept: + return Keywords.cNOEXCEPT; + case IASTUnaryExpression.op_throw: + return Keywords.cTHROW; + case IASTUnaryExpression.op_typeid: + return Keywords.cTYPEID; + case IASTUnaryExpression.op_alignOf: + return Keywords.cALIGNOF; + case IASTUnaryExpression.op_amper: + return Keywords.cpAMPER; + case IASTUnaryExpression.op_minus: + return Keywords.cpMINUS; + case IASTUnaryExpression.op_not: + return Keywords.cpNOT; + case IASTUnaryExpression.op_plus: + return Keywords.cpPLUS; + case IASTUnaryExpression.op_postFixDecr: + case IASTUnaryExpression.op_prefixDecr: + return Keywords.cpDECR; + case IASTUnaryExpression.op_postFixIncr: + case IASTUnaryExpression.op_prefixIncr: + return Keywords.cpINCR; + case IASTUnaryExpression.op_sizeof: + return Keywords.cSIZEOF; + case IASTUnaryExpression.op_sizeofParameterPack: + return Keywords.cSIZEOFPACK; + case IASTUnaryExpression.op_star: + return Keywords.cpSTAR; + case IASTUnaryExpression.op_tilde: + return Keywords.cpCOMPL; + } + + return CharArrayUtils.EMPTY; + } + + /** + * Returns the char[] representation of the IASTBinaryExpression's operator. + */ + public static char[] getBinaryOperatorString(IASTBinaryExpression be) { + switch (be.getOperator()) { + case IASTBinaryExpression.op_multiply: + return Keywords.cpSTAR; + case IASTBinaryExpression.op_divide: + return Keywords.cpDIV; + case IASTBinaryExpression.op_modulo: + return Keywords.cpMOD; + case IASTBinaryExpression.op_plus: + return Keywords.cpPLUS; + case IASTBinaryExpression.op_minus: + return Keywords.cpMINUS; + case IASTBinaryExpression.op_shiftLeft: + return Keywords.cpSHIFTL; + case IASTBinaryExpression.op_shiftRight: + return Keywords.cpSHIFTR; + case IASTBinaryExpression.op_lessThan: + return Keywords.cpLT; + case IASTBinaryExpression.op_greaterThan: + return Keywords.cpGT; + case IASTBinaryExpression.op_lessEqual: + return Keywords.cpLTEQUAL; + case IASTBinaryExpression.op_greaterEqual: + return Keywords.cpGTEQUAL; + case IASTBinaryExpression.op_binaryAnd: + return Keywords.cpAMPER; + case IASTBinaryExpression.op_binaryXor: + return Keywords.cpXOR; + case IASTBinaryExpression.op_binaryOr: + return Keywords.cpBITOR; + case IASTBinaryExpression.op_logicalAnd: + return Keywords.cpAND; + case IASTBinaryExpression.op_logicalOr: + return Keywords.cpOR; + case IASTBinaryExpression.op_assign: + return Keywords.cpASSIGN; + case IASTBinaryExpression.op_multiplyAssign: + return Keywords.cpSTARASSIGN; + case IASTBinaryExpression.op_divideAssign: + return Keywords.cpDIVASSIGN; + case IASTBinaryExpression.op_moduloAssign: + return Keywords.cpMODASSIGN; + case IASTBinaryExpression.op_plusAssign: + return Keywords.cpPLUSASSIGN; + case IASTBinaryExpression.op_minusAssign: + return Keywords.cpMINUSASSIGN; + case IASTBinaryExpression.op_shiftLeftAssign: + return Keywords.cpSHIFTLASSIGN; + case IASTBinaryExpression.op_shiftRightAssign: + return Keywords.cpSHIFTRASSIGN; + case IASTBinaryExpression.op_binaryAndAssign: + return Keywords.cpAMPERASSIGN; + case IASTBinaryExpression.op_binaryXorAssign: + return Keywords.cpXORASSIGN; + case IASTBinaryExpression.op_binaryOrAssign: + return Keywords.cpBITORASSIGN; + case IASTBinaryExpression.op_equals: + return Keywords.cpEQUAL; + case IASTBinaryExpression.op_notequals: + return Keywords.cpNOTEQUAL; + case IASTBinaryExpression.op_max: + return Keywords.cpMAX; + case IASTBinaryExpression.op_min: + return Keywords.cpMIN; + case IASTBinaryExpression.op_pmarrow: + return Keywords.cpARROW; + case IASTBinaryExpression.op_pmdot: + return Keywords.cpDOT; + } + + return CharArrayUtils.EMPTY; + } + + private static String getTypeIdExpressionOperator(IASTTypeIdExpression expression) { + switch (expression.getOperator()) { + case IASTTypeIdExpression.op_alignof: + return Keywords.ALIGNOF; + case IASTTypeIdExpression.op_typeof: + return Keywords.TYPEOF; + case ICPPASTTypeIdExpression.op_typeid: + return Keywords.TYPEID; + case IASTTypeIdExpression.op_sizeof: + return Keywords.SIZEOF; + } + return ""; //$NON-NLS-1$ + } + + /** + * Returns the String representation of the pack expansion expression. + * @param buffer + */ + private static StringBuilder appendPackExpansionExpression(StringBuilder buffer, + ICPPASTPackExpansionExpression expression) { + appendExpressionString(buffer, expression.getPattern()); + return buffer.append(Keywords.cpELLIPSIS); + } + + public static String getName(IASTDeclSpecifier decl) { + StringBuilder buffer = new StringBuilder(); + return ASTStringUtil.appendBareDeclSpecifierString(buffer,decl).toString(); + } +} \ No newline at end of file diff --git a/data/undertestsrc/java/depends/extractor/cpp/cdt/CDTParser.java b/data/undertestsrc/java/depends/extractor/cpp/cdt/CDTParser.java new file mode 100644 index 0000000..7b663ca --- /dev/null +++ b/data/undertestsrc/java/depends/extractor/cpp/cdt/CDTParser.java @@ -0,0 +1,71 @@ +package depends.extractor.cpp.cdt; + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit; +import org.eclipse.cdt.core.dom.parser.IScannerExtensionConfiguration; +import org.eclipse.cdt.core.dom.parser.cpp.GPPScannerExtensionConfiguration; +import org.eclipse.cdt.core.parser.CodeReader; +import org.eclipse.cdt.core.parser.FileContent; +import org.eclipse.cdt.core.parser.IScanner; +import org.eclipse.cdt.core.parser.NullLogService; +import org.eclipse.cdt.core.parser.ParserLanguage; +import org.eclipse.cdt.core.parser.ParserMode; +import org.eclipse.cdt.core.parser.ScannerInfo; +import org.eclipse.cdt.internal.core.dom.parser.AbstractGNUSourceCodeParser; +import org.eclipse.cdt.internal.core.dom.parser.c.CASTTranslationUnit; +import org.eclipse.cdt.internal.core.dom.parser.cpp.GNUCPPSourceParser; +import org.eclipse.cdt.internal.core.parser.scanner.CPreprocessor; + +@SuppressWarnings("deprecation") +public class CDTParser { + List sysIncludePath = new ArrayList<>(); + + public CDTParser() { + } + + public CDTParser(List includesPath) { + for (String f:includesPath) { + File file = new File(f); + if (file.exists()) { + try { + sysIncludePath.add(file.getCanonicalPath()); + } catch (IOException e) { + } + }else { + //System.err.println("include path " + f + " does not exist!"); + } + } + } + NullLogService NULL_LOG = new NullLogService(); + Map macroMap = new HashMap<>(); + public IASTTranslationUnit parse(String file ) { + CodeReader cr; + try { + cr = new CodeReader(file); + return getTranslationUnitofCPP(file,new String(cr.buffer)); + } catch (IOException e) { + } + return new CASTTranslationUnit(); + } + + + private IASTTranslationUnit getTranslationUnitofCPP(String file, String content) { + IScannerExtensionConfiguration configuration = GPPScannerExtensionConfiguration + .getInstance(); + IScanner scanner = new CPreprocessor(FileContent.create(file, + content.toCharArray()), new ScannerInfo(new HashMap<>(),sysIncludePath.toArray(new String[] {})), ParserLanguage.CPP, + new NullLogService(), configuration, null); + AbstractGNUSourceCodeParser sourceCodeParser = new GNUCPPSourceParser( + scanner, ParserMode.COMPLETE_PARSE, new NullLogService(), + new GPPParserExtensionConfigurationExtension(), null); + IASTTranslationUnit astTranslationUnit = sourceCodeParser.parse(); + return astTranslationUnit; + } + +} diff --git a/data/undertestsrc/java/depends/extractor/cpp/cdt/CdtCppEntitiesListener.java b/data/undertestsrc/java/depends/extractor/cpp/cdt/CdtCppEntitiesListener.java new file mode 100644 index 0000000..370ab20 --- /dev/null +++ b/data/undertestsrc/java/depends/extractor/cpp/cdt/CdtCppEntitiesListener.java @@ -0,0 +1,276 @@ +package depends.extractor.cpp.cdt; + +import java.util.ArrayList; + +import org.codehaus.plexus.util.StringUtils; +import org.eclipse.cdt.core.dom.ast.ASTVisitor; +import org.eclipse.cdt.core.dom.ast.IASTCompositeTypeSpecifier; +import org.eclipse.cdt.core.dom.ast.IASTDeclSpecifier; +import org.eclipse.cdt.core.dom.ast.IASTDeclaration; +import org.eclipse.cdt.core.dom.ast.IASTDeclarator; +import org.eclipse.cdt.core.dom.ast.IASTEnumerationSpecifier; +import org.eclipse.cdt.core.dom.ast.IASTEnumerationSpecifier.IASTEnumerator; +import org.eclipse.cdt.core.dom.ast.IASTExpression; +import org.eclipse.cdt.core.dom.ast.IASTFunctionDeclarator; +import org.eclipse.cdt.core.dom.ast.IASTFunctionDefinition; +import org.eclipse.cdt.core.dom.ast.IASTParameterDeclaration; +import org.eclipse.cdt.core.dom.ast.IASTProblem; +import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclaration; +import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier.ICPPASTBaseSpecifier; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNamespaceDefinition; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTUsingDeclaration; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTUsingDirective; +import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTLinkageSpecification; +import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTProblemDeclaration; +import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTVisibilityLabel; + +import depends.entity.Expression; +import depends.entity.FunctionEntity; +import depends.entity.VarEntity; +import depends.entity.repo.EntityRepo; +import depends.entity.repo.IdGenerator; +import depends.importtypes.ExactMatchImport; +import depends.importtypes.FileImport; +import depends.importtypes.PackageWildCardImport; +import depends.relations.Inferer; + +public class CdtCppEntitiesListener extends ASTVisitor { + private CppHandlerContext context; + private IdGenerator idGenerator; + private PreprocessorHandler preprocessorHandler; + private EntityRepo entityRepo; + Inferer inferer; + private ExpressionUsage expressionUsage; + public CdtCppEntitiesListener(String fileFullPath, EntityRepo entityRepo, PreprocessorHandler preprocessorHandler,Inferer inferer) { + super(true); + this.context = new CppHandlerContext(entityRepo); + idGenerator = entityRepo; + this.entityRepo = entityRepo; + this.inferer = inferer; + context.startFile(fileFullPath); + this.preprocessorHandler = preprocessorHandler; + expressionUsage = new ExpressionUsage(context,entityRepo); + } + + @Override + public int visit(IASTTranslationUnit tu) { + for (String incl:preprocessorHandler.getDirectIncludedFiles(tu.getAllPreprocessorStatements())) { + context.foundNewImport(new FileImport(incl)); + CdtCppFileParser importedParser = new CdtCppFileParser(incl, entityRepo, preprocessorHandler,inferer); + importedParser.parse(false); + } + MacroExtractor macroExtractor = new MacroExtractor(tu.getAllPreprocessorStatements()); + for (String var:macroExtractor.getMacroVars()) { + context.foundVarDefintion(var,Inferer.buildInType.getRawName()); + } + + for (String var:macroExtractor.getMacroFuncs()) { + context.foundMethodDeclarator(var, Inferer.buildInType.getRawName(), new ArrayList<>()); + context.exitLastedEntity(); + } + return super.visit(tu); + } + + + @Override + public int visit(IASTProblem problem) { + System.out.println("warning: parse error" + problem.getOriginalNode() + problem.getMessageWithLocation()); + return super.visit(problem); + } + + // PACKAGES + @Override + public int visit(ICPPASTNamespaceDefinition namespaceDefinition) { + String ns = namespaceDefinition.getName().toString().replace("::", "."); + context.foundNamespace(ns); + context.foundNewImport(new PackageWildCardImport(ns)); + return super.visit(namespaceDefinition); + } + + + @Override + public int leave(ICPPASTNamespaceDefinition namespaceDefinition) { + context.exitLastedEntity(); + return super.leave(namespaceDefinition); + } + + // Types + @Override + public int visit(IASTDeclSpecifier declSpec) { + if (declSpec instanceof IASTCompositeTypeSpecifier) { + IASTCompositeTypeSpecifier type = (IASTCompositeTypeSpecifier)declSpec; + context.foundNewType(type.getName().toString()); + if (declSpec instanceof ICPPASTCompositeTypeSpecifier) { + ICPPASTBaseSpecifier[] baseSpecififers = ((ICPPASTCompositeTypeSpecifier)declSpec).getBaseSpecifiers(); + for (ICPPASTBaseSpecifier baseSpecififer:baseSpecififers) { + String extendName = new String(baseSpecififer.getNameSpecifier().toCharArray()); + context.foundExtends(extendName); + } + } + } + else if (declSpec instanceof IASTEnumerationSpecifier) { + IASTEnumerationSpecifier type = (IASTEnumerationSpecifier)declSpec; + context.foundNewType(type.getName().toString()); + }else { + //we do not care other types + } + return super.visit(declSpec); + } + + @Override + public int leave(IASTDeclSpecifier declSpec) { + if (declSpec instanceof IASTCompositeTypeSpecifier) { + context.exitLastedEntity(); + } + else if (declSpec instanceof IASTEnumerationSpecifier) { + context.exitLastedEntity(); + }else { + //we do not care other types + } + return super.leave(declSpec); + } + + //Function or Methods + @Override + public int visit(IASTDeclarator declarator) { + if (declarator instanceof IASTFunctionDeclarator){ + String returnType = null; + if ( declarator.getParent() instanceof IASTSimpleDeclaration) { + IASTSimpleDeclaration decl = (IASTSimpleDeclaration)(declarator.getParent()); + returnType = ASTStringUtil.getName(decl.getDeclSpecifier()); + String rawName = declarator.getName().toString(); + FunctionEntity namedEntity = context.currentFile().lookupFunctionInVisibleScope(rawName); + if (namedEntity!=null) { + rawName = namedEntity.getQualifiedName(); + } + returnType = reMapIfConstructDeconstruct(rawName,returnType); + context.foundMethodDeclarator(rawName, returnType, new ArrayList<>()); + } + else if ( declarator.getParent() instanceof IASTFunctionDefinition) { + IASTFunctionDefinition decl = (IASTFunctionDefinition)declarator.getParent(); + returnType= ASTStringUtil.getReturnTypeString(decl.getDeclSpecifier(), decl.getDeclarator()); + String rawName = declarator.getName().toString(); + FunctionEntity namedEntity = context.currentFile().lookupFunctionInVisibleScope(rawName); + if (namedEntity!=null) { + rawName = namedEntity.getQualifiedName(); + } + returnType = reMapIfConstructDeconstruct(rawName,returnType); + context.foundMethodDeclarator(rawName, returnType, new ArrayList<>()); + } + } + return super.visit(declarator); + } + + /** + * In case of return type is empty, it maybe a construct/deconstruct function + * @param functionname + * @param returnType + * @return + */ + private String reMapIfConstructDeconstruct(String functionname, String returnType) { + if (returnType.length()>0) return returnType; + if (functionname.contains("::")) { + return functionname.substring(0, functionname.indexOf("::")); + }else { + return functionname; + } + } + + @Override + public int leave(IASTDeclarator declarator) { + if (declarator instanceof IASTFunctionDeclarator){ + if ( declarator.getParent() instanceof IASTSimpleDeclaration) { + String rawName = declarator.getName().toString(); + if (rawName.equals(context.lastContainer().getRawName())) { + context.exitLastedEntity(); + }else { + System.err.println("unexpected symbol"); + } + } + } + return super.leave(declarator); + } + + @Override + public int leave(IASTDeclaration declaration) { + if ( declaration instanceof IASTFunctionDefinition) { + context.exitLastedEntity(); + } + return super.leave(declaration); + } + + // Variables + @Override + public int visit(IASTDeclaration declaration) { + + if (declaration instanceof ICPPASTUsingDeclaration) { + String ns = ((ICPPASTUsingDeclaration)declaration).getName().toString().replace("::", "."); + context.foundNewImport(new PackageWildCardImport(ns)); + } + else if (declaration instanceof ICPPASTUsingDirective) { + String ns = ((ICPPASTUsingDirective)declaration).getQualifiedName().toString().replace("::", "."); + context.foundNewImport(new ExactMatchImport(ns)); + } + else if (declaration instanceof IASTSimpleDeclaration ) { + + for (IASTDeclarator declarator:((IASTSimpleDeclaration) declaration).getDeclarators()) { + IASTDeclSpecifier declSpecifier = ((IASTSimpleDeclaration) declaration).getDeclSpecifier(); + //Found new typedef definition + if (declSpecifier.getStorageClass()==IASTDeclSpecifier.sc_typedef) { + context.foundNewTypeAlias(declarator.getName().toString(),ASTStringUtil.getName(declSpecifier)); + }else if (!(declarator instanceof IASTFunctionDeclarator)) { + String varType = ASTStringUtil.getName(declSpecifier); + String varName = declarator.getName().toString(); + if (!StringUtils.isEmpty(varType)) { + context.foundVarDefintion(varName, varType); + }else { + expressionUsage.foundCallExpressionOfFunctionStyle(varName,declarator); + } + + } + } + }else if (declaration instanceof IASTFunctionDefinition){ + //handled in declarator + }else if (declaration instanceof CPPASTVisibilityLabel){ + //we ignore the visibility in dependency check + }else if (declaration instanceof CPPASTLinkageSpecification){ + + }else if (declaration instanceof CPPASTProblemDeclaration){ + System.err.println("parsing error \n" + declaration.getRawSignature()); + }else { + System.out.println(declaration.getClass().getName()); + System.out.println(declaration.getRawSignature()); + } + return super.visit(declaration); + } + + + + + @Override + public int visit(IASTEnumerator enumerator) { + context.foundVarDefintion(enumerator.getName().toString(), context.currentType().getRawName()); + return super.visit(enumerator); + } + + @Override + public int visit(IASTExpression expression) { + expressionUsage.foundExpression(expression); + return super.visit(expression); + } + + @Override + public int visit(IASTParameterDeclaration parameterDeclaration) { + String parameterName = parameterDeclaration.getDeclarator().getName().toString(); + String parameterType = ASTStringUtil.getName(parameterDeclaration.getDeclSpecifier()); + if (context.currentFunction()!=null) { + VarEntity var = new VarEntity(parameterName,parameterType,context.currentFunction(),idGenerator.generateId()); + context.currentFunction().addParameter(var ); + }else { + //System.out.println("** parameterDeclaration = " + parameter); + } + return super.visit(parameterDeclaration); + } +} \ No newline at end of file diff --git a/data/undertestsrc/java/depends/extractor/cpp/cdt/CdtCppFileParser.java b/data/undertestsrc/java/depends/extractor/cpp/cdt/CdtCppFileParser.java new file mode 100644 index 0000000..d4f26bf --- /dev/null +++ b/data/undertestsrc/java/depends/extractor/cpp/cdt/CdtCppFileParser.java @@ -0,0 +1,50 @@ +package depends.extractor.cpp.cdt; + +import java.io.IOException; + +import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit; + +import depends.entity.Entity; +import depends.entity.FileEntity; +import depends.entity.repo.EntityRepo; +import depends.extractor.cpp.CppFileParser; +import depends.relations.Inferer; +import depends.util.FileUtil; + +public class CdtCppFileParser extends CppFileParser { + + private PreprocessorHandler preprocessorHandler ; + private Inferer inferer; + + public CdtCppFileParser(String fileFullPath, EntityRepo entityRepo,PreprocessorHandler preprocessorHandler, Inferer inferer) { + super(fileFullPath, entityRepo,inferer); + this.preprocessorHandler = preprocessorHandler; + this.fileFullPath = FileUtil.uniqFilePath(fileFullPath); + this.inferer = inferer; + + } + @Override + public void parse() throws IOException { + parse(true); + } + + /** + * + * @param isInScope whether the parse is invoked by project file or an 'indirect' included file + */ + public void parse(boolean isInScope) { + /** If file already exist, skip it */ + Entity fileEntity = entityRepo.getEntity(fileFullPath); + if (fileEntity!=null && fileEntity instanceof FileEntity) { + FileEntity t = ((FileEntity)fileEntity); + if (!t.isInProjectScope() && isInScope) + t.setInProjectScope(true); + return; + } + + CdtCppEntitiesListener bridge = new CdtCppEntitiesListener(fileFullPath, entityRepo, preprocessorHandler,inferer); + IASTTranslationUnit translationUnit = (new CDTParser(preprocessorHandler.getIncludePaths())).parse(fileFullPath); + translationUnit.accept(bridge); + } + +} diff --git a/data/undertestsrc/java/depends/extractor/cpp/cdt/CommentManager.java b/data/undertestsrc/java/depends/extractor/cpp/cdt/CommentManager.java new file mode 100644 index 0000000..a1f96ba --- /dev/null +++ b/data/undertestsrc/java/depends/extractor/cpp/cdt/CommentManager.java @@ -0,0 +1,61 @@ +package depends.extractor.cpp.cdt; + +import org.eclipse.cdt.core.dom.ast.IASTComment; +import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit; +import org.eclipse.cdt.internal.core.dom.parser.ASTTranslationUnit; + +public class CommentManager { + + private IASTTranslationUnit translationUnit; + IASTComment[] comments; + boolean[] joinWithNext; + public CommentManager(IASTTranslationUnit translationUnit) { + this.translationUnit = translationUnit; + comments = ((ASTTranslationUnit) translationUnit).getComments(); + joinWithNext = new boolean[comments.length]; + + + for (int i=1;i=0) { + if (joinWithNext[i]) { + comment = new String(comments[i].getComment())+comment; + i--; + }else { + break; + } + } + return comment; + } + private int findCommentIndex(int startOffset) { + + IASTComment[] comments = ((ASTTranslationUnit) translationUnit).getComments(); + int i=0; + for (;i0 && gap<10) { + break; + } + if (gap<0) return -1; + } + return i>=comments.length?-1:i; + } +} diff --git a/data/undertestsrc/java/depends/extractor/cpp/cdt/CppHandlerContext.java b/data/undertestsrc/java/depends/extractor/cpp/cdt/CppHandlerContext.java new file mode 100644 index 0000000..a9f9c95 --- /dev/null +++ b/data/undertestsrc/java/depends/extractor/cpp/cdt/CppHandlerContext.java @@ -0,0 +1,20 @@ +package depends.extractor.cpp.cdt; + +import depends.entity.Entity; +import depends.entity.PackageEntity; +import depends.entity.repo.EntityRepo; +import depends.extractor.HandlerContext; + +public class CppHandlerContext extends HandlerContext { + + public CppHandlerContext(EntityRepo entityRepo) { + super(entityRepo); + } + + public Entity foundNamespace(String nampespaceName) { + PackageEntity pkgEntity = new PackageEntity(nampespaceName, currentFile(),idGenerator.generateId()); + entityRepo.add(pkgEntity); + entityStack.push(pkgEntity); + return pkgEntity; + } +} diff --git a/data/undertestsrc/java/depends/extractor/cpp/cdt/ExpressionUsage.java b/data/undertestsrc/java/depends/extractor/cpp/cdt/ExpressionUsage.java new file mode 100644 index 0000000..92e4391 --- /dev/null +++ b/data/undertestsrc/java/depends/extractor/cpp/cdt/ExpressionUsage.java @@ -0,0 +1,190 @@ +package depends.extractor.cpp.cdt; +import org.eclipse.cdt.core.dom.ast.IASTNode; +import org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression; +import org.eclipse.cdt.core.dom.ast.IASTUnaryExpression; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNewExpression; +import org.eclipse.cdt.core.dom.ast.IASTBinaryExpression; +import org.eclipse.cdt.core.dom.ast.IASTCastExpression; +import org.eclipse.cdt.core.dom.ast.IASTDeclaration; +import org.eclipse.cdt.core.dom.ast.IASTDeclarator; +import org.eclipse.cdt.core.dom.ast.IASTExpression; +import org.eclipse.cdt.core.dom.ast.IASTFunctionCallExpression; +import org.eclipse.cdt.core.dom.ast.IASTIdExpression; +import org.eclipse.cdt.core.dom.ast.IASTLiteralExpression; + +import depends.entity.Expression; +import depends.entity.repo.IdGenerator; +import depends.extractor.HandlerContext; + +public class ExpressionUsage { + HandlerContext context; + IdGenerator idGenerator; + public ExpressionUsage(HandlerContext context,IdGenerator idGenerator) { + this.context = context; + this.idGenerator = idGenerator; + } + + public void foundCallExpressionOfFunctionStyle(String functionName, IASTDeclarator declarator) { + /* create expression and link it with parent*/ + Expression expression = new Expression(idGenerator.generateId(),null); + context.lastContainer().addExpression(declarator,expression); + expression.isCall = true; + expression.identifier = functionName; + } + + public void foundExpression(IASTExpression ctx) { + Expression parent = findParentInStack(ctx); + /* create expression and link it with parent*/ + Expression expression = new Expression(idGenerator.generateId(),parent==null?null:parent.id); + expression.text = ctx.getRawSignature(); //for debug purpose. no actual effect + context.lastContainer().addExpression(ctx,expression); + + if (parent!=null) { + if (parent.deduceTypeBasedId==null) parent.deduceTypeBasedId = expression.id; + expression.parent = parent; + } + + + if (isTerminalExpression(ctx)) { + tryFillExpressionTypeAndIdentifier(ctx,expression); + return; + } + + expression.isSet = isSet(ctx); + expression.isCall = (ctx instanceof IASTFunctionCallExpression)?true:false; + expression.isLogic = isLogic(ctx); + if (ctx instanceof ICPPASTNewExpression){ + expression.isCreate = true; + } + expression.isDot = isDot(ctx); + + /** + * | expression bop='.' + ( IDENTIFIER + | methodCall + ) + */ + + //method call + if (ctx instanceof IASTFunctionCallExpression) { + expression.identifier = getMethodCallIdentifier((IASTFunctionCallExpression)ctx); + expression.isCall = true; + } + if (ctx instanceof ICPPASTNewExpression) { + expression.rawType = ASTStringUtil.getTypeIdString(((ICPPASTNewExpression)ctx).getTypeId()); + expression.isCall = true; + expression.deriveTypeFromChild = false; + } + + if (ctx instanceof IASTCastExpression) { + expression.isCast=true; + expression.rawType = ASTStringUtil.getTypeIdString(((IASTCastExpression)ctx).getTypeId()); + expression.deriveTypeFromChild = false; + + } + if (expression.isDot) { + IASTExpression op2 = ((IASTBinaryExpression)ctx).getOperand2(); + if (op2 instanceof IASTIdExpression) + expression.identifier = ((IASTIdExpression)op2).getName().toString(); + else if (op2 instanceof IASTLiteralExpression) + expression.identifier = ((IASTLiteralExpression)op2).getRawSignature(); + else if (op2 instanceof IASTFunctionCallExpression) + expression.identifier = getMethodCallIdentifier((IASTFunctionCallExpression)op2); + return; + } + } + + private boolean isTerminalExpression(IASTExpression ctx) { + if(ctx instanceof IASTIdExpression) return true; + if(ctx instanceof IASTLiteralExpression) return true; + if(ctx instanceof IASTTypeIdExpression) return true; + //TODO: add others + return false; + } + + private void tryFillExpressionTypeAndIdentifier(IASTExpression ctx, Expression expression) { + + //1. we only handle leaf node. if there is still expression, + // the type will be determined by child node in the expression + if (ctx instanceof IASTIdExpression){ + expression.identifier = ((IASTIdExpression) ctx).getName().toString(); + }else if (ctx instanceof IASTLiteralExpression) { + //2. if it is a var name, dertermine the type based on context. + expression.identifier = ""; + expression.rawType = ""; + }else if (ctx instanceof IASTTypeIdExpression) { + //3. if given type directly + expression.rawType = ASTStringUtil.getTypeIdString(((IASTTypeIdExpression)ctx).getTypeId()); + //TODO: check + } + } + + private String getMethodCallIdentifier(IASTFunctionCallExpression methodCall) { + IASTExpression f = methodCall.getFunctionNameExpression(); + if (f instanceof IASTIdExpression) { + return ((IASTIdExpression)f).getName().toString(); + } + return null; + } + + private boolean isDot(IASTExpression ctx) { + if (ctx instanceof IASTBinaryExpression) { + int op = ((IASTBinaryExpression)ctx).getOperator(); + if (op==IASTBinaryExpression.op_pmdot || + op==IASTBinaryExpression.op_pmarrow ) return true; + } + return false; + } + + private boolean isLogic(IASTExpression ctx) { + if (ctx instanceof IASTBinaryExpression) { + int op = ((IASTBinaryExpression)ctx).getOperator(); + + if (op == IASTBinaryExpression.op_equals || + op == IASTBinaryExpression.op_notequals || + op == IASTBinaryExpression.op_lessThan || + op == IASTBinaryExpression.op_lessEqual || + op == IASTBinaryExpression.op_greaterThan || + op == IASTBinaryExpression.op_greaterEqual || + op == IASTBinaryExpression.op_logicalAnd || + op == IASTBinaryExpression.op_logicalOr + ) { + return true; + } + } + return false; + } + + public boolean isSet(IASTExpression ctx) { + if (ctx instanceof IASTBinaryExpression) { + int op = ((IASTBinaryExpression)ctx).getOperator(); + if (op>=IASTBinaryExpression.op_assign && + op<=IASTBinaryExpression.op_binaryOrAssign) { + return true; + } + } + if (ctx instanceof IASTUnaryExpression) { + int op = ((IASTUnaryExpression)ctx).getOperator(); + if (op == IASTUnaryExpression.op_prefixIncr || + op == IASTUnaryExpression.op_prefixDecr || + op == IASTUnaryExpression.op_postFixIncr || + op == IASTUnaryExpression.op_postFixIncr + ) + return true; + } + return false; + } + + + private Expression findParentInStack(IASTNode ctx) { + if (ctx==null) return null; + if (ctx.getParent()==null) return null; + if (context.lastContainer()==null) { + return null; + } + if (context.lastContainer().expressions().containsKey(ctx.getParent())) return context.lastContainer().expressions().get(ctx.getParent()); + return findParentInStack(ctx.getParent()); + } + + +} \ No newline at end of file diff --git a/data/undertestsrc/java/depends/extractor/cpp/cdt/GPPParserExtensionConfigurationExtension.java b/data/undertestsrc/java/depends/extractor/cpp/cdt/GPPParserExtensionConfigurationExtension.java new file mode 100644 index 0000000..dba4da6 --- /dev/null +++ b/data/undertestsrc/java/depends/extractor/cpp/cdt/GPPParserExtensionConfigurationExtension.java @@ -0,0 +1,22 @@ +package depends.extractor.cpp.cdt; + +import org.eclipse.cdt.core.dom.parser.cpp.GPPParserExtensionConfiguration; + +class GPPParserExtensionConfigurationExtension extends GPPParserExtensionConfiguration { + + @Override + public boolean supportKnRC() { + return false; + } + + @Override + public boolean supportParameterInfoBlock() { + return false; + } + + @Override + public boolean supportStatementsInExpressions() { + return false; + } + +} diff --git a/data/undertestsrc/java/depends/extractor/cpp/cdt/MacroExtractor.java b/data/undertestsrc/java/depends/extractor/cpp/cdt/MacroExtractor.java new file mode 100644 index 0000000..06dd6d4 --- /dev/null +++ b/data/undertestsrc/java/depends/extractor/cpp/cdt/MacroExtractor.java @@ -0,0 +1,31 @@ +package depends.extractor.cpp.cdt; + +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.cdt.core.dom.ast.IASTPreprocessorFunctionStyleMacroDefinition; +import org.eclipse.cdt.core.dom.ast.IASTPreprocessorObjectStyleMacroDefinition; +import org.eclipse.cdt.core.dom.ast.IASTPreprocessorStatement; + +public class MacroExtractor { + ArrayList macroVars = new ArrayList<>(); + ArrayList macroFuncs = new ArrayList<>(); + + public MacroExtractor(IASTPreprocessorStatement[] statements) { + for (int statementIndex=0;statementIndex getMacroVars() { + return macroVars; + } + public List getMacroFuncs() { + return macroFuncs; + } +} diff --git a/data/undertestsrc/java/depends/extractor/cpp/cdt/PreprocessorHandler.java b/data/undertestsrc/java/depends/extractor/cpp/cdt/PreprocessorHandler.java new file mode 100644 index 0000000..2a52c60 --- /dev/null +++ b/data/undertestsrc/java/depends/extractor/cpp/cdt/PreprocessorHandler.java @@ -0,0 +1,49 @@ +package depends.extractor.cpp.cdt; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; + +import org.eclipse.cdt.core.dom.ast.IASTPreprocessorIncludeStatement; +import org.eclipse.cdt.core.dom.ast.IASTPreprocessorStatement; + +import depends.util.FileUtil; + +public class PreprocessorHandler { + private HashMap notExistedIncludedFiles = new HashMap<>(); + public Collection getNotExistedIncludedFiles() { + return notExistedIncludedFiles.values(); + } + private List includePaths; + public PreprocessorHandler(List includePaths){ + notExistedIncludedFiles = new HashMap<>(); + this.setIncludePaths(includePaths); + } + public List getDirectIncludedFiles(IASTPreprocessorStatement[] statements) { + ArrayList includedFullPathNames = new ArrayList<>(); + for (int statementIndex=0;statementIndex getIncludePaths() { + return includePaths; + } + public void setIncludePaths(List includePaths) { + this.includePaths = includePaths; + } +} diff --git a/data/undertestsrc/java/depends/extractor/java/JavaBuiltInType.java b/data/undertestsrc/java/depends/extractor/java/JavaBuiltInType.java new file mode 100644 index 0000000..266ef2c --- /dev/null +++ b/data/undertestsrc/java/depends/extractor/java/JavaBuiltInType.java @@ -0,0 +1,64 @@ +package depends.extractor.java; + +import depends.entity.repo.BuiltInType; + +public class JavaBuiltInType extends BuiltInType{ + + public JavaBuiltInType() { + super.createBuiltInTypes(); + } + @Override + public String[] getBuiltInTypeStr() { + return new String[]{ + "void","int","double","char","byte","boolean","long","short","float", + "BigDecimal","Integer","Double","Char","Byte","Boolean","Long","Short","Float", + "String","Object","Class","Exception","StringBuilder", + "Appendable","AutoCloseable","Cloneable","Comparable","Iterable","Readable", + "Runnable","Thread.UncaughtExceptionHandler","Boolean","Byte","Character","Character.Subset", + "Character.UnicodeBlock","ClassLoader","ClassValue","Compiler","Double","Enum", + "InheritableThreadLocal","Math","Number","Package","Process", + "ProcessBuilder","ProcessBuilder.Redirect","Runtime","RuntimePermission", + "SecurityManager","StackTraceElement","StrictMath","StringBuffer", + "System","Thread","ThreadGroup","ThreadLocal","Throwable","Void","ProcessBuilder.Redirect.Type", + "Thread.State","ArithmeticException","ArrayIndexOutOfBoundsException", + "ArrayStoreException","ClassCastException","ClassNotFoundException","CloneNotSupportedException", + "EnumConstantNotPresentException","Exception","IllegalAccessException","IllegalArgumentException", + "IllegalMonitorStateException","IllegalStateException","IllegalThreadStateException", + "IndexOutOfBoundsException","InstantiationException","InterruptedException", + "NegativeArraySizeException","NoSuchFieldException","NoSuchMethodException","NullPointerException", + "NumberFormatException","ReflectiveOperationException","RuntimeException","SecurityException", + "StringIndexOutOfBoundsException","TypeNotPresentException","UnsupportedOperationException","AbstractMethodError", + "AssertionError","BootstrapMethodError","ClassCircularityError","ClassFormatError","Error","ExceptionInInitializerError", + "IllegalAccessError","IncompatibleClassChangeError","InstantiationError","InternalError","LinkageError","NoClassDefFoundError" + ,"NoSuchFieldError","NoSuchMethodError","OutOfMemoryError","StackOverflowError","ThreadDeath","UnknownError", + "UnsatisfiedLinkError","UnsupportedClassVersionError","VerifyError","VirtualMachineError","Deprecated","Override", + "SafeVarargs","SuppressWarnings", + "Collection","Comparator","Deque","Enumeration","EventListener","Formattable","Iterator","List", + "ListIterator","Map","Map.Entry","NavigableMap","NavigableSet","Observer","Queue","RandomAccess", + "Set","SortedMap","SortedSet","AbstractCollection","AbstractList","AbstractMap","AbstractMap.SimpleEntry", + "AbstractMap.SimpleImmutableEntry","AbstractQueue","AbstractSequentialList","AbstractSet","ArrayDeque", + "ArrayList","Arrays","BitSet","Calendar","Collections","Currency","Date","Dictionary","EnumMap","EnumSet", + "EventListenerProxy","EventObject","FormattableFlags","Formatter","GregorianCalendar","HashMap","HashSet", + "Hashtable","IdentityHashMap","LinkedHashMap","LinkedHashSet","LinkedList","ListResourceBundle","Locale", + "Locale.Builder","Objects","Observable","PriorityQueue","Properties","PropertyPermission", + "PropertyResourceBundle","Random","ResourceBundle","ResourceBundle.Control","Scanner", + "ServiceLoader","SimpleTimeZone","Stack","StringTokenizer","Timer","TimerTask","TimeZone", + "TreeMap","TreeSet","UUID","Vector","WeakHashMap","Formatter.BigDecimalLayoutForm", + "Locale.Category","ConcurrentModificationException","DuplicateFormatFlagsException", + "EmptyStackException","FormatFlagsConversionMismatchException","FormatterClosedException", + "IllegalFormatCodePointException","IllegalFormatConversionException","IllegalFormatException", + "IllegalFormatFlagsException","IllegalFormatPrecisionException","IllegalFormatWidthException", + "IllformedLocaleException","InputMismatchException","InvalidPropertiesFormatException","MissingFormatArgumentException", + "MissingFormatWidthException","MissingResourceException","NoSuchElementException","TooManyListenersException", + "UnknownFormatConversionException","UnknownFormatFlagsException","ServiceConfigurationError", + "" + }; + } + @Override + public String[] getBuiltInPrefixStr() { + return new String[]{ + "java.","javax.","com.sun." + }; + } + +} diff --git a/data/undertestsrc/java/depends/extractor/java/JavaEntitiesListener.java b/data/undertestsrc/java/depends/extractor/java/JavaEntitiesListener.java new file mode 100644 index 0000000..9b9f4b8 --- /dev/null +++ b/data/undertestsrc/java/depends/extractor/java/JavaEntitiesListener.java @@ -0,0 +1,325 @@ +package depends.extractor.java; + +import java.util.ArrayList; +import java.util.List; + +import depends.entity.FunctionEntity; +import depends.entity.repo.EntityRepo; +import depends.extractor.java.context.AnnotationProcessor; +import depends.extractor.java.context.ClassTypeContextHelper; +import depends.extractor.java.context.ExpressionUsage; +import depends.extractor.java.context.FormalParameterListContextHelper; +import depends.extractor.java.context.IdentifierContextHelper; +import depends.extractor.java.context.QualitiedNameContextHelper; +import depends.extractor.java.context.TypeParameterContextHelper; +import depends.extractor.java.context.VariableDeclaratorsContextHelper; +import depends.importtypes.ExactMatchImport; +import depends.extractor.java.JavaParser.AnnotationConstantRestContext; +import depends.extractor.java.JavaParser.AnnotationMethodRestContext; +import depends.extractor.java.JavaParser.AnnotationTypeDeclarationContext; +import depends.extractor.java.JavaParser.BlockContext; +import depends.extractor.java.JavaParser.ClassDeclarationContext; +import depends.extractor.java.JavaParser.ConstDeclarationContext; +import depends.extractor.java.JavaParser.ConstructorDeclarationContext; +import depends.extractor.java.JavaParser.EnhancedForControlContext; +import depends.extractor.java.JavaParser.EnumConstantContext; +import depends.extractor.java.JavaParser.EnumDeclarationContext; +import depends.extractor.java.JavaParser.ExpressionContext; +import depends.extractor.java.JavaParser.FieldDeclarationContext; +import depends.extractor.java.JavaParser.ImportDeclarationContext; +import depends.extractor.java.JavaParser.InterfaceDeclarationContext; +import depends.extractor.java.JavaParser.InterfaceMethodDeclarationContext; +import depends.extractor.java.JavaParser.LocalVariableDeclarationContext; +import depends.extractor.java.JavaParser.MethodDeclarationContext; +import depends.extractor.java.JavaParser.PackageDeclarationContext; +import depends.extractor.java.JavaParser.ResourceContext; +import depends.extractor.java.JavaParser.TypeParameterContext; +import depends.extractor.java.JavaParser.TypeParametersContext; +import depends.extractor.java.JavaParserBaseListener; + +public class JavaEntitiesListener extends JavaParserBaseListener { + private JavaHandlerContext context; + private AnnotationProcessor annotationProcessor; + private ExpressionUsage expressionUsage; + private EntityRepo entityRepo; + + public JavaEntitiesListener(String fileFullPath, EntityRepo entityRepo) { + this.context = new JavaHandlerContext(entityRepo); + this.entityRepo = entityRepo; + annotationProcessor = new AnnotationProcessor(context); + expressionUsage = new ExpressionUsage(context,entityRepo); + context.startFile(fileFullPath); + } + + //////////////////////// + // Package + @Override + public void enterPackageDeclaration(PackageDeclarationContext ctx) { + context.foundNewPackage(QualitiedNameContextHelper.getName(ctx.qualifiedName())); + super.enterPackageDeclaration(ctx); + } + + //////////////////////// + // Import + @Override + public void enterImportDeclaration(ImportDeclarationContext ctx) { + context.foundNewImport(new ExactMatchImport(ctx.qualifiedName().getText())); + super.enterImportDeclaration(ctx); + } + + /////////////////////// + // Class or Interface + // classDeclaration | enumDeclaration | interfaceDeclaration | + /////////////////////// annotationTypeDeclaration + @Override + public void enterClassDeclaration(ClassDeclarationContext ctx) { + context.foundNewType(ctx.IDENTIFIER().getText()); + // implements + if (ctx.typeList() != null) { + for (int i = 0; i < ctx.typeList().typeType().size(); i++) { + context.foundImplements(ClassTypeContextHelper.getClassName(ctx.typeList().typeType().get(i))); + } + } + // extends relation + if (ctx.typeType() != null) { + context.foundExtends(ClassTypeContextHelper.getClassName(ctx.typeType())); + } + + if (ctx.typeParameters() != null) { + foundTypeParametersUse(ctx.typeParameters()); + } + annotationProcessor.processAnnotationModifier(ctx, "classOrInterfaceModifier"); + super.enterClassDeclaration(ctx); + } + + @Override + public void exitClassDeclaration(ClassDeclarationContext ctx) { + exitLastEntity(); + super.exitClassDeclaration(ctx); + } + + @Override + public void enterEnumDeclaration(EnumDeclarationContext ctx) { + context.foundNewType(ctx.IDENTIFIER().getText()); + annotationProcessor.processAnnotationModifier(ctx, "classOrInterfaceModifier"); + super.enterEnumDeclaration(ctx); + } + + @Override + public void exitEnumDeclaration(EnumDeclarationContext ctx) { + exitLastEntity(); + super.exitEnumDeclaration(ctx); + } + + /** + * interfaceDeclaration : INTERFACE IDENTIFIER typeParameters? (EXTENDS + * typeList)? interfaceBody ; + */ + @Override + public void enterInterfaceDeclaration(InterfaceDeclarationContext ctx) { + context.foundNewType(ctx.IDENTIFIER().getText()); + // type parameters + if (ctx.typeParameters() != null) { + foundTypeParametersUse(ctx.typeParameters()); + } + // extends relation + if (ctx.typeList() != null) { + for (int i = 0; i < ctx.typeList().typeType().size(); i++) { + context.foundExtends(ClassTypeContextHelper.getClassName(ctx.typeList().typeType().get(i))); + } + } + annotationProcessor.processAnnotationModifier(ctx, "classOrInterfaceModifier"); + super.enterInterfaceDeclaration(ctx); + } + + @Override + public void exitInterfaceDeclaration(InterfaceDeclarationContext ctx) { + exitLastEntity(); + super.exitInterfaceDeclaration(ctx); + } + + @Override + public void enterAnnotationTypeDeclaration(AnnotationTypeDeclarationContext ctx) { + context.foundNewType(ctx.IDENTIFIER().getText()); + annotationProcessor.processAnnotationModifier(ctx, "classOrInterfaceModifier"); + super.enterAnnotationTypeDeclaration(ctx); + } + + @Override + public void exitAnnotationTypeDeclaration(AnnotationTypeDeclarationContext ctx) { + exitLastEntity(); + super.exitAnnotationTypeDeclaration(ctx); + } + + ///////////////////////// + // Method + @Override + public void enterMethodDeclaration(MethodDeclarationContext ctx) { + List throwedType = QualitiedNameContextHelper.getNames(ctx.qualifiedNameList()); + String methodName = ctx.IDENTIFIER().getText(); + String returnedType = ClassTypeContextHelper.getClassName(ctx.typeTypeOrVoid()); + FunctionEntity method = context.foundMethodDeclarator(methodName, returnedType, throwedType); + new FormalParameterListContextHelper(ctx.formalParameters(), method, entityRepo); + if (ctx.typeParameters() != null) { + List parameters = TypeParameterContextHelper.getTypeParameters(ctx.typeParameters()); + method.addTypeParameter(parameters); + } + annotationProcessor.processAnnotationModifier(ctx, "classOrInterfaceModifier"); + super.enterMethodDeclaration(ctx); + } + + @Override + public void exitMethodDeclaration(MethodDeclarationContext ctx) { + exitLastEntity(); + super.exitMethodDeclaration(ctx); + } + + private void exitLastEntity() { + context.exitLastedEntity(); + } + +// interfaceMethodDeclaration +// : interfaceMethodModifier* (typeTypeOrVoid | typeParameters annotation* typeTypeOrVoid) +// IDENTIFIER formalParameters ('[' ']')* (THROWS qualifiedNameList)? methodBody + + @Override + public void enterInterfaceMethodDeclaration(InterfaceMethodDeclarationContext ctx) { + List throwedType = QualitiedNameContextHelper.getNames(ctx.qualifiedNameList()); + FunctionEntity method = context.foundMethodDeclarator(ctx.IDENTIFIER().getText(), + ClassTypeContextHelper.getClassName(ctx.typeTypeOrVoid()), throwedType); + new FormalParameterListContextHelper(ctx.formalParameters(), method, entityRepo); + if (ctx.typeParameters() != null) { + foundTypeParametersUse(ctx.typeParameters()); + } + annotationProcessor.processAnnotationModifier(ctx, "interfaceMethodModifier"); + super.enterInterfaceMethodDeclaration(ctx); + } + + @Override + public void exitInterfaceMethodDeclaration(InterfaceMethodDeclarationContext ctx) { + exitLastEntity(); + super.exitInterfaceMethodDeclaration(ctx); + } + + @Override + public void enterConstructorDeclaration(ConstructorDeclarationContext ctx) { + List throwedType = QualitiedNameContextHelper.getNames(ctx.qualifiedNameList()); + FunctionEntity method = context.foundMethodDeclarator(ctx.IDENTIFIER().getText(), ctx.IDENTIFIER().getText(), + throwedType); + new FormalParameterListContextHelper(ctx.formalParameters(), method, entityRepo); + method.setReturnType(context.currentType()); + annotationProcessor.processAnnotationModifier(ctx, "classBodyDeclaration"); + super.enterConstructorDeclaration(ctx); + } + + @Override + public void exitConstructorDeclaration(ConstructorDeclarationContext ctx) { + exitLastEntity(); + super.exitConstructorDeclaration(ctx); + } + + ///////////////////////////////////////////////////////// + // Field + @Override + public void enterFieldDeclaration(FieldDeclarationContext ctx) { + List varNames = VariableDeclaratorsContextHelper.getVariables(ctx.variableDeclarators()); + String type = ClassTypeContextHelper.getClassName(ctx.typeType()); + context.foundVarDefinition(varNames, type); + annotationProcessor.processAnnotationModifier(ctx, "classBodyDeclaration"); + super.enterFieldDeclaration(ctx); + } + + @Override + public void enterConstDeclaration(ConstDeclarationContext ctx) { + context.foundVarDefinition(VariableDeclaratorsContextHelper.getVariables(ctx.constantDeclarator()), + ClassTypeContextHelper.getClassName(ctx.typeType())); + annotationProcessor.processAnnotationModifier(ctx, "interfaceBodyDeclaration"); + super.enterConstDeclaration(ctx); + } + + @Override + public void enterEnumConstant(EnumConstantContext ctx) { + if (ctx.IDENTIFIER() != null) + context.foundEnumConstDefinition(ctx.IDENTIFIER().getText()); + super.enterEnumConstant(ctx); + } + + @Override + public void enterAnnotationMethodRest(AnnotationMethodRestContext ctx) { + context.foundMethodDeclarator(ctx.IDENTIFIER().getText(), ClassTypeContextHelper.getClassName(ctx.typeType()), + new ArrayList<>()); + super.enterAnnotationMethodRest(ctx); + } + + @Override + public void exitAnnotationMethodRest(AnnotationMethodRestContext ctx) { + exitLastEntity(); + super.exitAnnotationMethodRest(ctx); + } + + @Override + public void enterAnnotationConstantRest(AnnotationConstantRestContext ctx) { + // TODO: no variable type defined in annotation const? + context.foundVarDefinition(VariableDeclaratorsContextHelper.getVariables(ctx.variableDeclarators()), ""); + super.enterAnnotationConstantRest(ctx); + } + + /////////////////////////////////////////// + // variables + // TODO: all modifier have not processed yet. + @Override + public void enterLocalVariableDeclaration(LocalVariableDeclarationContext ctx) { + context.foundVarDefinition(VariableDeclaratorsContextHelper.getVariables((ctx.variableDeclarators())), + ClassTypeContextHelper.getClassName(ctx.typeType())); + super.enterLocalVariableDeclaration(ctx); + } + + public void enterEnhancedForControl(EnhancedForControlContext ctx) { + context.foundVarDefinition(VariableDeclaratorsContextHelper.getVariable((ctx.variableDeclaratorId())), + ClassTypeContextHelper.getClassName(ctx.typeType())); + super.enterEnhancedForControl(ctx); + } + +// resource +// : variableModifier* classOrInterfaceType variableDeclaratorId '=' expression +// ; + @Override + public void enterResource(ResourceContext ctx) { + context.foundVarDefintion(ctx.variableDeclaratorId().IDENTIFIER().getText(), + IdentifierContextHelper.getName(ctx.classOrInterfaceType().IDENTIFIER())); + super.enterResource(ctx); + } + + @Override + public void enterExpression(ExpressionContext ctx) { + expressionUsage.foundExpression(ctx); + super.enterExpression(ctx); + } + + ///////////////////////////////////////////// + // Block + @Override + public void enterBlock(BlockContext ctx) { + // TODO Auto-generated method stub + super.enterBlock(ctx); + } + + @Override + public void exitBlock(BlockContext ctx) { + // TODO Auto-generated method stub + super.exitBlock(ctx); + } + + /* type parameters , <> treat as USE */ + private void foundTypeParametersUse(TypeParametersContext typeParameters) { + for (int i = 0; i < typeParameters.typeParameter().size(); i++) { + TypeParameterContext typeParam = typeParameters.typeParameter(i); + if (typeParam.typeBound() != null) { + for (int j = 0; j < typeParam.typeBound().typeType().size(); j++) { + context.foundTypeParametes(ClassTypeContextHelper.getClassName(typeParam.typeBound().typeType(j))); + } + } + context.currentType().addTypeParameter(typeParam.IDENTIFIER().getText()); + } + } +} diff --git a/data/undertestsrc/java/depends/extractor/java/JavaFileParser.java b/data/undertestsrc/java/depends/extractor/java/JavaFileParser.java new file mode 100644 index 0000000..7966a30 --- /dev/null +++ b/data/undertestsrc/java/depends/extractor/java/JavaFileParser.java @@ -0,0 +1,36 @@ +package depends.extractor.java; + +import java.io.IOException; + +import org.antlr.v4.runtime.CharStream; +import org.antlr.v4.runtime.CharStreams; +import org.antlr.v4.runtime.CommonTokenStream; +import org.antlr.v4.runtime.Lexer; +import org.antlr.v4.runtime.tree.ParseTreeWalker; + +import depends.entity.repo.EntityRepo; +import depends.extractor.java.JavaLexer; +import depends.extractor.java.JavaParser; +import depends.relations.Inferer; + + +public class JavaFileParser implements depends.extractor.FileParser{ + private String fileFullPath; + private EntityRepo entityRepo; + public JavaFileParser(String fileFullPath,EntityRepo entityRepo, Inferer inferer) { + this.fileFullPath = fileFullPath; + this.entityRepo = entityRepo; + } + + + public void parse() throws IOException { + CharStream input = CharStreams.fromFileName(fileFullPath); + Lexer lexer = new JavaLexer(input); + CommonTokenStream tokens = new CommonTokenStream(lexer); + JavaParser parser = new JavaParser(tokens); + JavaEntitiesListener bridge = new JavaEntitiesListener(fileFullPath, entityRepo); + ParseTreeWalker walker = new ParseTreeWalker(); + walker.walk(bridge, parser.compilationUnit()); + } + +} diff --git a/data/undertestsrc/java/depends/extractor/java/JavaHandlerContext.java b/data/undertestsrc/java/depends/extractor/java/JavaHandlerContext.java new file mode 100644 index 0000000..164e494 --- /dev/null +++ b/data/undertestsrc/java/depends/extractor/java/JavaHandlerContext.java @@ -0,0 +1,23 @@ +package depends.extractor.java; + +import depends.entity.Entity; +import depends.entity.PackageEntity; +import depends.entity.repo.EntityRepo; +import depends.extractor.HandlerContext; + +public class JavaHandlerContext extends HandlerContext { + + public JavaHandlerContext(EntityRepo entityRepo) { + super(entityRepo); + } + + public Entity foundNewPackage(String packageName) { + Entity pkgEntity = entityRepo.getEntity(packageName); + if (pkgEntity == null) { + pkgEntity = new PackageEntity(packageName, idGenerator.generateId()); + entityRepo.add(pkgEntity); + } + entityRepo.setParent(currentFileEntity,pkgEntity); + return pkgEntity; + } +} diff --git a/data/undertestsrc/java/depends/extractor/java/JavaImportLookupStrategy.java b/data/undertestsrc/java/depends/extractor/java/JavaImportLookupStrategy.java new file mode 100644 index 0000000..2afdc9f --- /dev/null +++ b/data/undertestsrc/java/depends/extractor/java/JavaImportLookupStrategy.java @@ -0,0 +1,54 @@ +package depends.extractor.java; + +import java.util.ArrayList; +import java.util.List; + +import depends.entity.Entity; +import depends.entity.FileEntity; +import depends.entity.PackageEntity; +import depends.entity.repo.EntityRepo; +import depends.importtypes.Import; +import depends.relations.ImportLookupStrategy; +import depends.relations.Inferer; + +public class JavaImportLookupStrategy implements ImportLookupStrategy{ + @Override + public Entity lookupImportedType(String name, FileEntity fileEntity, EntityRepo repo, Inferer inferer) { + //Java Strategy + String importedString = fileEntity.importedSuffixMatch(name); + if (importedString==null) return null; + return repo.getEntity(importedString); + } + + + @Override + public List getImportedRelationEntities(List importedList, EntityRepo repo) { + ArrayList result = new ArrayList<>(); + for (Import importedItem:importedList) { + Entity imported = repo.getEntity(importedItem.getContent()); + if (imported==null) continue; + if (imported instanceof PackageEntity) { + //expand import of package to all classes under the package due to we dis-courage the behavior + for (Entity child:imported.getChildren()) { + result.add(child); + } + }else { + result.add(imported); + } + } + return result; + } + + @Override + public List getImportedTypes(List importedList, EntityRepo repo) { + return getImportedRelationEntities(importedList,repo); + } + + @Override + public List getImportedFiles(List importedList, EntityRepo repo) { + return new ArrayList(); + } + + + +} diff --git a/data/undertestsrc/java/depends/extractor/java/JavaWorker.java b/data/undertestsrc/java/depends/extractor/java/JavaWorker.java new file mode 100644 index 0000000..f1fecc1 --- /dev/null +++ b/data/undertestsrc/java/depends/extractor/java/JavaWorker.java @@ -0,0 +1,40 @@ +package depends.extractor.java; + +import java.util.ArrayList; +import java.util.List; + +import depends.extractor.AbstractLangWorker; +import depends.extractor.FileParser; +import depends.relations.Inferer; + +public class JavaWorker extends AbstractLangWorker { + public static final String JAVA_LANG = "java"; + public static final String JAVA_SUFFIX = ".java"; + + public JavaWorker(String inputDir, String[] includeDir) { + super(inputDir,includeDir); + inferer = new Inferer(entityRepo,new JavaImportLookupStrategy(),new JavaBuiltInType()); + } + + @Override + public String supportedLanguage() { + return JAVA_LANG; + } + + @Override + public String[] fileSuffixes() { + return new String[] {JAVA_SUFFIX}; + } + + + @Override + protected FileParser getFileParser(String fileFullPath) { + return new JavaFileParser(fileFullPath,entityRepo, inferer); + } + + + @Override + public List getErrors() { + return new ArrayList(); + } +} diff --git a/data/undertestsrc/java/depends/extractor/java/context/AnnotationProcessor.java b/data/undertestsrc/java/depends/extractor/java/context/AnnotationProcessor.java new file mode 100644 index 0000000..c8ce1b9 --- /dev/null +++ b/data/undertestsrc/java/depends/extractor/java/context/AnnotationProcessor.java @@ -0,0 +1,70 @@ +package depends.extractor.java.context; + +import java.lang.reflect.Method; +import java.util.List; + +import org.antlr.v4.runtime.RuleContext; + +import depends.extractor.HandlerContext; +import depends.extractor.java.JavaParser.AnnotationContext; + +public class AnnotationProcessor { + private HandlerContext context; + + public AnnotationProcessor(HandlerContext context) { + this.context = context; + } + /** + * for any elements who with modifiers like 'public/static/... @Annotation‘, + * process annotations as "USE" + * + * @param ctx + * @param class1 + */ + + private boolean containsMethod(RuleContext ctx,String methodName) { + try { + Method m = ctx.getClass().getMethod(methodName); + if (m!=null) return true; + } catch (Exception e) { + return false; + } + return true; + } + private Method getMethod(RuleContext ctx, String methodName) { + try { + Method m = ctx.getClass().getMethod(methodName); + if (m!=null) return m; + } catch (Exception e) { + return null; + } + return null; + } + + public void processAnnotationModifier(RuleContext ctx, String methodName) { + while (true) { + if (ctx == null) + break; + if (containsMethod(ctx,methodName)) + break; + ctx = ctx.parent; + } + if (ctx==null)return; + + Method m = getMethod(ctx,methodName); + if (m==null) return; + try { + List modifiers = (List) m.invoke(ctx); + for (Object modifier : modifiers) { + Method annotationMethod = modifier.getClass().getMethod("annotation"); + AnnotationContext annotation = (AnnotationContext) (annotationMethod.invoke(modifier)); + if (annotation == null) + return; + String name = QualitiedNameContextHelper.getName(annotation.qualifiedName()); + context.foundAnnotation(name); + } + } catch (Exception e) { + return; + } + } +} diff --git a/data/undertestsrc/java/depends/extractor/java/context/ClassTypeContextHelper.java b/data/undertestsrc/java/depends/extractor/java/context/ClassTypeContextHelper.java new file mode 100644 index 0000000..2efb605 --- /dev/null +++ b/data/undertestsrc/java/depends/extractor/java/context/ClassTypeContextHelper.java @@ -0,0 +1,39 @@ +package depends.extractor.java.context; + +import depends.extractor.java.JavaParser.ClassOrInterfaceTypeContext; +import depends.extractor.java.JavaParser.TypeTypeContext; +import depends.extractor.java.JavaParser.TypeTypeOrVoidContext; + +public class ClassTypeContextHelper { + + /** + typeType + : annotation? (classOrInterfaceType | primitiveType) ('[' ']')* + ; + classOrInterfaceType + : IDENTIFIER typeArguments? ('.' IDENTIFIER typeArguments?)* + ; + */ + public static String getClassName(TypeTypeContext ctx) { + if (ctx.primitiveType()!=null) + return ctx.primitiveType().getText(); + if (ctx.classOrInterfaceType()!=null) + return getType(ctx.classOrInterfaceType()); + return null; + } + + private static String getType(ClassOrInterfaceTypeContext ctx) { + String r = ""; + for (int i=0;i0) + return creator.createdName().IDENTIFIER(0).getText(); + return null; + } +} diff --git a/data/undertestsrc/java/depends/extractor/java/context/ExpressionUsage.java b/data/undertestsrc/java/depends/extractor/java/context/ExpressionUsage.java new file mode 100644 index 0000000..719a70d --- /dev/null +++ b/data/undertestsrc/java/depends/extractor/java/context/ExpressionUsage.java @@ -0,0 +1,182 @@ +package depends.extractor.java.context; + +import org.antlr.v4.runtime.RuleContext; + +import depends.entity.Expression; +import depends.entity.repo.IdGenerator; +import depends.extractor.HandlerContext; +import depends.extractor.java.JavaParser.ExpressionContext; +import depends.extractor.java.JavaParser.MethodCallContext; +import depends.extractor.java.JavaParser.PrimaryContext; + +public class ExpressionUsage { + HandlerContext context; + IdGenerator idGenerator; + public ExpressionUsage(HandlerContext context,IdGenerator idGenerator) { + this.context = context; + this.idGenerator = idGenerator; + } + + public void foundExpression(ExpressionContext ctx) { + Expression parent = findParentInStack(ctx); + /* create expression and link it with parent*/ + Expression expression = new Expression(idGenerator.generateId(),parent==null?null:parent.id); + context.lastContainer().addExpression(ctx,expression); + + expression.text = ctx.getText(); //for debug purpose. no actual effect + expression.parent = parent; + if (expression.parent!=null) { + if (expression.parent.deduceTypeBasedId==null) + expression.parent.deduceTypeBasedId = expression.id; + } + + if (ctx.primary()!=null) { + tryFillExpressionTypeAndIdentifier(ctx.primary(),expression); + return; + } + + expression.isSet = isSet(ctx); + expression.isCall = ctx.methodCall()==null?false:true; + expression.isLogic = isLogic(ctx); + expression.isDot = isDot(ctx); + if (ctx.creator()!=null ||ctx.innerCreator()!=null){ + expression.isCreate = true; + } +/** + * | expression bop='.' + ( IDENTIFIER + | methodCall + | THIS + | NEW nonWildcardTypeArguments? innerCreator + | SUPER superSuffix + | explicitGenericInvocation + ) + */ + //method call + if (ctx.methodCall()!=null) { + expression.identifier = getMethodCallIdentifier(ctx.methodCall()); + expression.isCall = true; + } + //new + if (ctx.NEW()!=null && ctx.creator()!=null) { + expression.rawType = CreatorContextHelper.getCreatorType(ctx.creator()); + expression.isCall = true; + expression.deriveTypeFromChild = false; + } + + if (ctx.typeCast()!=null) { + expression.isCast=true; + expression.rawType = ctx.typeCast().typeType().getText(); + expression.deriveTypeFromChild = false; + } + + if (ctx.bop!=null && ctx.bop.getText().equals("instanceof")) { + expression.isCast=true; + expression.rawType = ctx.typeType().getText(); + expression.deriveTypeFromChild = false; + } + + if (ctx.creator()!=null) { + expression.deriveTypeFromChild = false; + } + + if (expression.isDot) { + if (ctx.IDENTIFIER()!=null) + expression.identifier = ctx.IDENTIFIER().getText(); + else if (ctx.methodCall()!=null) + expression.identifier = getMethodCallIdentifier(ctx.methodCall()); + else if (ctx.THIS()!=null) + expression.identifier = "this"; + else if (ctx.innerCreator()!=null) //innner creator like new List(){} + expression.identifier = ctx.innerCreator().IDENTIFIER().getText(); + else if (ctx.SUPER()!=null) + expression.identifier = "super"; + return; + } + } + + private String getMethodCallIdentifier(MethodCallContext methodCall) { + if (methodCall.THIS()!=null) { + return "this"; + }else if (methodCall.SUPER()!=null) { + return "super"; + }else { + return methodCall.IDENTIFIER().getText(); + } + } + + private boolean isDot(ExpressionContext ctx) { + if (ctx.bop!=null) + if (ctx.bop.getText().equals(".")) return true; + return false; + } + + private boolean isLogic(ExpressionContext ctx) { + if (ctx.bop != null) { + if (OpHelper.isLogic(ctx.bop.getText())) { + return true; + } + } + return false; + } + + public boolean isSet(ExpressionContext ctx) { + if (ctx.bop != null) { + if (OpHelper.isAssigment(ctx.bop.getText())) { + return true; + } + } + if (ctx.prefix != null) { + if (OpHelper.isIncrementalDecremental(ctx.prefix.getText())) { + return true; + } + } + if (ctx.postfix != null) { + if (OpHelper.isIncrementalDecremental(ctx.postfix.getText())) { + return true; + } + } + + return false; + } + +// primary +// : '(' expression ')' +// | THIS +// | SUPER +// | literal +// | IDENTIFIER +// | typeTypeOrVoid '.' CLASS +// | nonWildcardTypeArguments (explicitGenericInvocationSuffix | THIS arguments) //Just USE relation +// + private void tryFillExpressionTypeAndIdentifier(PrimaryContext ctx, Expression expression) { + if (ctx.expression()!=null) return; + //1. we only handle leaf node. if there is still expression, + // the type will be determined by child node in the expression + if (ctx.literal()!=null) { + //2. if it is a build-in type like "hello"(string), 10(integer), etc. + expression.rawType = ""; + expression.identifier = ""; + }else if (ctx.IDENTIFIER()!=null) { + //2. if it is a var name, dertermine the type based on context. + expression.identifier = ctx.IDENTIFIER().getText(); + }else if (ctx.typeTypeOrVoid()!=null) { + //3. if given type directly + expression.rawType = ClassTypeContextHelper.getClassName(ctx.typeTypeOrVoid()); + }else if (ctx.THIS()!=null){ + expression.identifier = "this"; + }else if (ctx.SUPER()!=null){ + expression.identifier = "super"; + } + } + + private Expression findParentInStack(RuleContext ctx) { + if (ctx==null) return null; + if (ctx.parent==null) return null; + if (context.lastContainer()==null) { + return null; + } + if (context.lastContainer().expressions().containsKey(ctx.parent)) return context.lastContainer().expressions().get(ctx.parent); + return findParentInStack(ctx.parent); + } +} diff --git a/data/undertestsrc/java/depends/extractor/java/context/FormalParameterListContextHelper.java b/data/undertestsrc/java/depends/extractor/java/context/FormalParameterListContextHelper.java new file mode 100644 index 0000000..a8486f2 --- /dev/null +++ b/data/undertestsrc/java/depends/extractor/java/context/FormalParameterListContextHelper.java @@ -0,0 +1,74 @@ +package depends.extractor.java.context; + +import java.util.ArrayList; +import java.util.List; + +import org.antlr.v4.runtime.tree.TerminalNode; + +import depends.entity.FunctionEntity; +import depends.entity.VarEntity; +import depends.entity.repo.IdGenerator; +import depends.extractor.java.JavaParser.FormalParameterContext; +import depends.extractor.java.JavaParser.FormalParameterListContext; +import depends.extractor.java.JavaParser.FormalParametersContext; +import depends.extractor.java.JavaParser.LastFormalParameterContext; +import depends.extractor.java.JavaParser.TypeTypeContext; +import depends.extractor.java.JavaParser.VariableModifierContext; + +public class FormalParameterListContextHelper { + + FormalParameterListContext context; + private IdGenerator idGenerator; + private List annotations; + private FunctionEntity container; + + public FormalParameterListContextHelper(FormalParameterListContext formalParameterListContext,FunctionEntity container, IdGenerator idGenerator) { + this.context = formalParameterListContext; + this.container = container; + annotations = new ArrayList<>(); + this.idGenerator = idGenerator; + if (context!=null) + extractParameterTypeList(); + } + + public FormalParameterListContextHelper(FormalParametersContext formalParameters,FunctionEntity container, IdGenerator idGenerator) { + this(formalParameters.formalParameterList(),container,idGenerator); + } + + + + public void extractParameterTypeList() { + if (context != null) { + if (context.formalParameter() != null) { + for (FormalParameterContext p : context.formalParameter()) { + foundParameterDefintion(p.typeType(),p.variableDeclaratorId().IDENTIFIER(),p.variableModifier()); + } + if (context.lastFormalParameter()!=null) { + LastFormalParameterContext p = context.lastFormalParameter(); + foundParameterDefintion(p.typeType(),p.variableDeclaratorId().IDENTIFIER(),p.variableModifier()); + } + } + } + return; + } + + private void foundParameterDefintion(TypeTypeContext typeType, TerminalNode identifier, List variableModifier) { + String type = ClassTypeContextHelper.getClassName(typeType); + String varName = identifier.getText(); + VarEntity varEntity = new VarEntity(varName,type,container,idGenerator.generateId()); + container.addParameter(varEntity); + + for ( VariableModifierContext modifier:variableModifier) { + if (modifier.annotation()!=null) { + this.annotations.add(QualitiedNameContextHelper.getName(modifier.annotation().qualifiedName())); + } + } + + } + + public List getAnnotations() { + return annotations; + } + + +} diff --git a/data/undertestsrc/java/depends/extractor/java/context/IdentifierContextHelper.java b/data/undertestsrc/java/depends/extractor/java/context/IdentifierContextHelper.java new file mode 100644 index 0000000..76f3071 --- /dev/null +++ b/data/undertestsrc/java/depends/extractor/java/context/IdentifierContextHelper.java @@ -0,0 +1,16 @@ +package depends.extractor.java.context; + +import java.util.List; + +import org.antlr.v4.runtime.tree.TerminalNode; + +public class IdentifierContextHelper { + public static String getName(List identifiers) { + String r = ""; + for (TerminalNode id:identifiers) { + String dot = r.isEmpty()?"":"."; + r = r + dot + id.getText(); + } + return r; + } +} diff --git a/data/undertestsrc/java/depends/extractor/java/context/OpHelper.java b/data/undertestsrc/java/depends/extractor/java/context/OpHelper.java new file mode 100644 index 0000000..56f548e --- /dev/null +++ b/data/undertestsrc/java/depends/extractor/java/context/OpHelper.java @@ -0,0 +1,37 @@ +package depends.extractor.java.context; + +//: primary +//| expression bop='.' +// ( IDENTIFIER +// | methodCall +// | THIS +// | NEW nonWildcardTypeArguments? innerCreator +// | SUPER superSuffix +// | explicitGenericInvocation +// ) +//| expression '[' expression ']' +//| methodCall +//| NEW creator +//| '(' typeType ')' expression +//| expression ('<' '<' | '>' '>' '>' | '>' '>') expression +//| expression bop=INSTANCEOF typeType +//| expression +// expression +//| lambdaExpression // Java8 +public class OpHelper { + public static boolean isLogic(String op) { + return op.equals("<") || op.equals(">") || op.equals("<=") || op.equals(">=") + || op.equals("==") + || op.equals("!=") || op.equals("&&") || op.equals("||") || op.equals("?"); + } + + public static boolean isAssigment(String op) { + return op.equals("=") || op.equals("+=") || op.equals("-=") || op.equals("*=") || op.equals("/=") + || op.equals("&=") || op.equals("|=") || op.equals("^=") || op.equals(">>=") || op.equals(">>>=") + || op.equals("<<=") || op.equals("%="); + } + + public static boolean isIncrementalDecremental(String op) { + return op.equals("++") || op.equals("--"); + } +} diff --git a/data/undertestsrc/java/depends/extractor/java/context/QualitiedNameContextHelper.java b/data/undertestsrc/java/depends/extractor/java/context/QualitiedNameContextHelper.java new file mode 100644 index 0000000..8eaeeff --- /dev/null +++ b/data/undertestsrc/java/depends/extractor/java/context/QualitiedNameContextHelper.java @@ -0,0 +1,28 @@ +package depends.extractor.java.context; + +import java.util.ArrayList; +import java.util.List; + +import depends.extractor.java.JavaParser.QualifiedNameContext; +import depends.extractor.java.JavaParser.QualifiedNameListContext; + +public class QualitiedNameContextHelper { + public static String getName(QualifiedNameContext ctx) { + String r = ""; + for (int i=0;i getNames(QualifiedNameListContext qualifiedNameList) { + List names = new ArrayList<>(); + if (qualifiedNameList == null) + return names; + for (QualifiedNameContext item : qualifiedNameList.qualifiedName()) { + names.add(getName(item)); + } + return names; + } +} diff --git a/data/undertestsrc/java/depends/extractor/java/context/TypeParameterContextHelper.java b/data/undertestsrc/java/depends/extractor/java/context/TypeParameterContextHelper.java new file mode 100644 index 0000000..b8e8e49 --- /dev/null +++ b/data/undertestsrc/java/depends/extractor/java/context/TypeParameterContextHelper.java @@ -0,0 +1,19 @@ +package depends.extractor.java.context; + +import java.util.ArrayList; +import java.util.List; + +import depends.extractor.java.JavaParser.TypeParameterContext; +import depends.extractor.java.JavaParser.TypeParametersContext; + +public class TypeParameterContextHelper { + + public static List getTypeParameters(TypeParametersContext typeParameters) { + ArrayList r = new ArrayList<>(); + for(TypeParameterContext param:typeParameters.typeParameter()) { + r.add(param.IDENTIFIER().getText()); + } + return r; + } + +} diff --git a/data/undertestsrc/java/depends/extractor/java/context/VariableDeclaratorsContextHelper.java b/data/undertestsrc/java/depends/extractor/java/context/VariableDeclaratorsContextHelper.java new file mode 100644 index 0000000..f74ecb2 --- /dev/null +++ b/data/undertestsrc/java/depends/extractor/java/context/VariableDeclaratorsContextHelper.java @@ -0,0 +1,40 @@ +package depends.extractor.java.context; + +import java.util.ArrayList; +import java.util.List; + +import depends.extractor.java.JavaParser.ConstantDeclaratorContext; +import depends.extractor.java.JavaParser.VariableDeclaratorContext; +import depends.extractor.java.JavaParser.VariableDeclaratorIdContext; +import depends.extractor.java.JavaParser.VariableDeclaratorsContext; + +public class VariableDeclaratorsContextHelper { + + public static List getVariables(VariableDeclaratorsContext variableDeclarators) { + List vars = new ArrayList<>(); + if (variableDeclarators==null) return vars; + for (VariableDeclaratorContext vContext:variableDeclarators.variableDeclarator()) { + vars.add(vContext.variableDeclaratorId().IDENTIFIER().getText()); + } + return vars; + } + + public static List getVariables(List constantDeclarator) { + List vars = new ArrayList<>(); + if (constantDeclarator==null) return vars; + for (ConstantDeclaratorContext vContext:constantDeclarator) { + vars.add(vContext.IDENTIFIER().getText()); + } + return vars; + } + + public static List getVariable(VariableDeclaratorIdContext variableDeclaratorIdContext) { + List vars = new ArrayList<>(); + if (variableDeclaratorIdContext==null) return vars; + vars.add(variableDeclaratorIdContext.IDENTIFIER().getText()); + return vars; + } + + + +} diff --git a/data/undertestsrc/java/depends/extractor/ruby/RubyBuiltInType.java b/data/undertestsrc/java/depends/extractor/ruby/RubyBuiltInType.java new file mode 100644 index 0000000..a849f51 --- /dev/null +++ b/data/undertestsrc/java/depends/extractor/ruby/RubyBuiltInType.java @@ -0,0 +1,23 @@ +package depends.extractor.ruby; + +import depends.entity.repo.BuiltInType; + +public class RubyBuiltInType extends BuiltInType { + public RubyBuiltInType() { + super.createBuiltInTypes(); + } + + @Override + public String[] getBuiltInTypeStr() { + return new String[] { "__ENCODING__", "__LINE__", "__FILE__", "BEGIN", "END", "alias", "and", "begin", "break", + "case", "class", "def", "defined?", "do", "else", "elsif", "end", "ensure", "false", "for", "if", "in", + "module", "next", "nil", "not", "or", "redo", "rescue", "retry", "return", "self", "super", "then", + "true", "undef", "unless", "until", "when", "while", "yield" }; + } + + @Override + public String[] getBuiltInPrefixStr() { + return new String[] {}; + } + +} diff --git a/data/undertestsrc/java/depends/extractor/ruby/RubyFileParser.java b/data/undertestsrc/java/depends/extractor/ruby/RubyFileParser.java new file mode 100644 index 0000000..d05e260 --- /dev/null +++ b/data/undertestsrc/java/depends/extractor/ruby/RubyFileParser.java @@ -0,0 +1,35 @@ +package depends.extractor.ruby; + +import java.io.IOException; + +import org.antlr.v4.runtime.CharStream; +import org.antlr.v4.runtime.CharStreams; +import org.antlr.v4.runtime.CommonTokenStream; +import org.antlr.v4.runtime.Lexer; +import org.antlr.v4.runtime.tree.ParseTreeWalker; + +import depends.entity.repo.EntityRepo; +import depends.extractor.FileParser; +import depends.extractor.java.JavaLexer; + +public class RubyFileParser implements FileParser { + private String fileFullPath; + private EntityRepo entityRepo; + + public RubyFileParser(String fileFullPath, EntityRepo entityRepo) { + this.fileFullPath = fileFullPath; + this.entityRepo = entityRepo; + } + + @Override + public void parse() throws IOException { + CharStream input = CharStreams.fromFileName(fileFullPath); + Lexer lexer = new JavaLexer(input); + CommonTokenStream tokens = new CommonTokenStream(lexer); + CorundumParser parser = new CorundumParser(tokens); + RubyListener bridge = new RubyListener(fileFullPath, entityRepo); + ParseTreeWalker walker = new ParseTreeWalker(); + walker.walk(bridge, parser.prog()); + } + +} diff --git a/data/undertestsrc/java/depends/extractor/ruby/RubyImportLookupStrategy.java b/data/undertestsrc/java/depends/extractor/ruby/RubyImportLookupStrategy.java new file mode 100644 index 0000000..93617e0 --- /dev/null +++ b/data/undertestsrc/java/depends/extractor/ruby/RubyImportLookupStrategy.java @@ -0,0 +1,38 @@ +package depends.extractor.ruby; + +import java.util.List; + +import depends.entity.Entity; +import depends.entity.FileEntity; +import depends.entity.repo.EntityRepo; +import depends.importtypes.Import; +import depends.relations.ImportLookupStrategy; +import depends.relations.Inferer; + +public class RubyImportLookupStrategy implements ImportLookupStrategy { + + @Override + public Entity lookupImportedType(String name, FileEntity fileEntity, EntityRepo repo, Inferer inferer) { + // TODO Auto-generated method stub + return null; + } + + @Override + public List getImportedRelationEntities(List importedNames, EntityRepo repo) { + // TODO Auto-generated method stub + return null; + } + + @Override + public List getImportedTypes(List importedNames, EntityRepo repo) { + // TODO Auto-generated method stub + return null; + } + + @Override + public List getImportedFiles(List importedNames, EntityRepo repo) { + // TODO Auto-generated method stub + return null; + } + +} diff --git a/data/undertestsrc/java/depends/extractor/ruby/RubyListener.java b/data/undertestsrc/java/depends/extractor/ruby/RubyListener.java new file mode 100644 index 0000000..7219ebb --- /dev/null +++ b/data/undertestsrc/java/depends/extractor/ruby/RubyListener.java @@ -0,0 +1,9 @@ +package depends.extractor.ruby; + +import depends.entity.repo.EntityRepo; + +public class RubyListener extends CorundumBaseListener{ + + public RubyListener(String fileFullPath, EntityRepo entityRepo) { + } +} diff --git a/data/undertestsrc/java/depends/extractor/ruby/RubyWorker.java b/data/undertestsrc/java/depends/extractor/ruby/RubyWorker.java new file mode 100644 index 0000000..823a4db --- /dev/null +++ b/data/undertestsrc/java/depends/extractor/ruby/RubyWorker.java @@ -0,0 +1,41 @@ +package depends.extractor.ruby; + +import java.util.ArrayList; +import java.util.List; + +import depends.extractor.AbstractLangWorker; +import depends.extractor.FileParser; +import depends.extractor.cpp.cdt.PreprocessorHandler; +import depends.relations.Inferer; + +public class RubyWorker extends AbstractLangWorker { + private static final String LANG = "ruby"; + private static final String[] SUFFIX = new String[] {".rb",".ruby"}; + PreprocessorHandler preprocessorHandler; + public RubyWorker(String inputDir, String[] includeDir) { + super(inputDir,includeDir); + preprocessorHandler = new PreprocessorHandler(super.includePaths()); + inferer = new Inferer(entityRepo,new RubyImportLookupStrategy(),new RubyBuiltInType()); + } + + + @Override + public String supportedLanguage() { + return LANG; + } + + @Override + public String[] fileSuffixes() { + return SUFFIX; + } + + + @Override + protected FileParser getFileParser(String fileFullPath) { + return new RubyFileParser(fileFullPath,entityRepo); + } + + public List getErrors(){ + return new ArrayList(preprocessorHandler.getNotExistedIncludedFiles()); + } +} diff --git a/data/undertestsrc/java/depends/format/AbstractFormatDependencyDumper.java b/data/undertestsrc/java/depends/format/AbstractFormatDependencyDumper.java new file mode 100644 index 0000000..a3a428e --- /dev/null +++ b/data/undertestsrc/java/depends/format/AbstractFormatDependencyDumper.java @@ -0,0 +1,23 @@ +package depends.format; + +import java.io.File; + +import depends.matrix.DependencyMatrix; + +public abstract class AbstractFormatDependencyDumper { + protected String name; + protected DependencyMatrix matrix; + protected String outputDir; + + public AbstractFormatDependencyDumper(DependencyMatrix matrix, String projectName, String outputDir) { + this.matrix = matrix; + this.name = projectName; + this.outputDir = outputDir; + } + + public abstract boolean output(); + public abstract String getFormatName(); + protected String composeFilename() { + return outputDir+File.separator+name; + } +} diff --git a/data/undertestsrc/java/depends/format/DependencyDumper.java b/data/undertestsrc/java/depends/format/DependencyDumper.java new file mode 100644 index 0000000..2f3f0b2 --- /dev/null +++ b/data/undertestsrc/java/depends/format/DependencyDumper.java @@ -0,0 +1,49 @@ +package depends.format; + +import java.util.List; + +import depends.format.detail.DetailTextFormatDependencyDumper; +import depends.format.dot.DotFormatDependencyDumper; +import depends.format.excel.ExcelFormatDependencyDumper; +import depends.format.json.JsonFormatDependencyDumper; +import depends.format.xml.XmlFormatDependencyDumper; +import depends.matrix.DependencyMatrix; +import edu.emory.mathcs.backport.java.util.Arrays; + +public class DependencyDumper { + + private DependencyMatrix dependencyMatrix; + private List errors; + + public DependencyDumper(DependencyMatrix dependencies, List errors) { + this.dependencyMatrix = dependencies; + this.errors = errors; + } + + public void outputResult(String projectName, String outputDir, String[] outputFormat) { + outputErrors(); + outputDeps(projectName,outputDir,outputFormat); + } + + private final void outputDeps(String projectName, String outputDir, String[] outputFormat) { + List formatList = Arrays.asList(outputFormat); + AbstractFormatDependencyDumper[] builders = new AbstractFormatDependencyDumper[] { + new DetailTextFormatDependencyDumper(dependencyMatrix,projectName,outputDir), + new XmlFormatDependencyDumper(dependencyMatrix,projectName,outputDir), + new JsonFormatDependencyDumper(dependencyMatrix,projectName,outputDir), + new ExcelFormatDependencyDumper(dependencyMatrix,projectName,outputDir), + new DotFormatDependencyDumper(dependencyMatrix,projectName,outputDir), + }; + for (AbstractFormatDependencyDumper builder:builders) { + if (formatList.contains(builder.getFormatName())){ + builder.output(); + } + } + } + + private void outputErrors() { + for (String e:errors) { + System.err.println(e); + } + } +} diff --git a/data/undertestsrc/java/depends/format/FileAttributes.java b/data/undertestsrc/java/depends/format/FileAttributes.java new file mode 100644 index 0000000..3225bea --- /dev/null +++ b/data/undertestsrc/java/depends/format/FileAttributes.java @@ -0,0 +1,18 @@ +package depends.format; + +public class FileAttributes { + private String schemaVersion = "1.0"; + private String attributeName; + public FileAttributes( String projectName) { + this.attributeName = projectName + "-sdsm"; + } + + public String getSchemaVersion() { + return schemaVersion; + } + + public String getAttributeName() { + return this.attributeName; + } +} + diff --git a/data/undertestsrc/java/depends/format/detail/DetailTextFormatDependencyDumper.java b/data/undertestsrc/java/depends/format/detail/DetailTextFormatDependencyDumper.java new file mode 100644 index 0000000..1d17fe1 --- /dev/null +++ b/data/undertestsrc/java/depends/format/detail/DetailTextFormatDependencyDumper.java @@ -0,0 +1,48 @@ +package depends.format.detail; + +import java.io.FileNotFoundException; +import java.io.PrintWriter; +import java.util.ArrayList; +import java.util.Collection; + +import depends.format.AbstractFormatDependencyDumper; +import depends.matrix.DependencyMatrix; +import depends.matrix.DependencyPair; +import depends.matrix.DependencyValue; + +public class DetailTextFormatDependencyDumper extends AbstractFormatDependencyDumper{ + ArrayList files; + @Override + public String getFormatName() { + return "detail"; + } + public DetailTextFormatDependencyDumper(DependencyMatrix matrix, String name, String outputDir) { + super(matrix,name,outputDir); + } + @Override + public boolean output() { + PrintWriter writer; + try { + files = matrix.getNodes(); + writer = new PrintWriter(composeFilename() +".txt"); + Collection dependencyPairs = matrix.getDependencyPairs(); + addRelations(writer,dependencyPairs); + writer.close(); + return true; + } catch (FileNotFoundException e) { + e.printStackTrace(); + return false; + } + } + + private void addRelations(PrintWriter writer, Collection dependencyPairs) { + for (DependencyPair dependencyPair:dependencyPairs) { + int src = dependencyPair.getFrom(); + int dst = dependencyPair.getTo(); + writer.println("======="+files.get(src) + " -> " + files.get(dst) + "========="); + for (DependencyValue dependency:dependencyPair.getDependencies()) { + writer.println(dependency.getDetails()); + } + } + } +} diff --git a/data/undertestsrc/java/depends/format/dot/DotFormatDependencyDumper.java b/data/undertestsrc/java/depends/format/dot/DotFormatDependencyDumper.java new file mode 100644 index 0000000..429debf --- /dev/null +++ b/data/undertestsrc/java/depends/format/dot/DotFormatDependencyDumper.java @@ -0,0 +1,52 @@ +package depends.format.dot; + +import java.io.FileNotFoundException; +import java.io.PrintWriter; +import java.util.ArrayList; +import java.util.Collection; + +import depends.format.AbstractFormatDependencyDumper; +import depends.matrix.DependencyMatrix; +import depends.matrix.DependencyPair; + +public class DotFormatDependencyDumper extends AbstractFormatDependencyDumper{ + @Override + public String getFormatName() { + return "dot"; + } + public DotFormatDependencyDumper(DependencyMatrix dependencyMatrix, String projectName, String outputDir) { + super(dependencyMatrix,projectName,outputDir); + } + @Override + public boolean output() { + PrintWriter writer; + try { + writer = new PrintWriter(composeFilename()+".dot"); + ArrayList files = matrix.getNodes(); + + for (int i=0;i dependencyPairs = matrix.getDependencyPairs(); + + addRelations(writer,dependencyPairs); + writer.println("}"); + writer.close(); + return true; + } catch (FileNotFoundException e) { + e.printStackTrace(); + return false; + } + } + + private void addRelations(PrintWriter writer, Collection dependencyPairs) { + for (DependencyPair dependencyPair:dependencyPairs) { + int src = dependencyPair.getFrom(); + int dst = dependencyPair.getTo(); + writer.println("\t"+src + " -> " + dst + ";"); + } + } +} diff --git a/data/undertestsrc/java/depends/format/excel/ExcelFormatDependencyDumper.java b/data/undertestsrc/java/depends/format/excel/ExcelFormatDependencyDumper.java new file mode 100644 index 0000000..67cc888 --- /dev/null +++ b/data/undertestsrc/java/depends/format/excel/ExcelFormatDependencyDumper.java @@ -0,0 +1,96 @@ +package depends.format.excel; + +import java.io.File; +import java.io.IOException; +import java.util.Collection; + +import org.apache.poi.hssf.usermodel.HSSFCell; +import org.apache.poi.hssf.usermodel.HSSFRow; +import org.apache.poi.hssf.usermodel.HSSFSheet; +import org.apache.poi.hssf.usermodel.HSSFWorkbook; + +import depends.format.AbstractFormatDependencyDumper; +import depends.matrix.DependencyMatrix; +import depends.matrix.DependencyPair; +import depends.matrix.DependencyValue; + +public class ExcelFormatDependencyDumper extends AbstractFormatDependencyDumper { + private HSSFWorkbook workbook; + private HSSFSheet sheet; + @Override + public String getFormatName() { + return "excel"; + } + public ExcelFormatDependencyDumper(DependencyMatrix dependencyMatrix, String projectName, String outputDir) { + super(dependencyMatrix, projectName,outputDir); + } + + @Override + public boolean output() { + String filename = composeFilename() + ".xls"; + if (matrix.getNodes().size() > 255) { + System.out.println("We can only export small matrix(<256 items) to excel" + "due to MS Office limitation"); + return false; + } + startFile(); + Collection dependencyPairs = matrix.getDependencyPairs(); + HSSFRow[] row = new HSSFRow[matrix.getNodes().size()]; + + // create header row + HSSFRow header = sheet.createRow(0); + for (int i = 0; i < matrix.getNodes().size(); i++) { + HSSFCell cell = header.createCell(i + 2); + cell.setCellValue(i); + } + ; + + // create header col + for (int i = 0; i < matrix.getNodes().size(); i++) { + row[i] = sheet.createRow(i + 1); + String node = matrix.getNodes().get(i); + HSSFCell cell = row[i].createCell(0); + cell.setCellValue(i); + cell = row[i].createCell(1); + cell.setCellValue(node); + } + ; + + // create header col + for (int i = 0; i < matrix.getNodes().size(); i++) { + HSSFCell cell = row[i].createCell(i + 2); + cell.setCellValue("(" + i + ")"); + } + ; + + for (DependencyPair dependencyPair : dependencyPairs) { + HSSFCell cell = row[dependencyPair.getFrom()].createCell(dependencyPair.getTo() + 2); + cell.setCellValue(buildDependencyValues(dependencyPair.getDependencies())); + } + closeFile(filename); + return true; + } + + private String buildDependencyValues(Collection dependencies) { + StringBuilder sb = new StringBuilder(); + for (DependencyValue dependency : dependencies) { + String comma = sb.length() > 0 ? "," : ""; + sb.append(comma).append(dependency.getType()).append("(").append(dependency.getWeight()).append(")"); + } + return sb.toString(); + } + + private void closeFile(String filename) { + try { + workbook.write(new File(filename)); + workbook.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + + private void startFile() { + workbook = new HSSFWorkbook(); + sheet = workbook.createSheet("DSM"); + } + +} diff --git a/data/undertestsrc/java/depends/format/json/JCellObject.java b/data/undertestsrc/java/depends/format/json/JCellObject.java new file mode 100644 index 0000000..bf94b05 --- /dev/null +++ b/data/undertestsrc/java/depends/format/json/JCellObject.java @@ -0,0 +1,41 @@ +package depends.format.json; + + +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; +import java.util.Map; + +@XmlRootElement(name = "cell") +public class JCellObject { + private int src; + private int dest; + private Map values; + + public int getSrc() { + return src; + } + + @XmlAttribute(name = "src") + public void setSrc(int src) { + this.src = src; + } + + public int getDest() { + return dest; + } + + @XmlAttribute(name = "dest") + public void setDest(int dest) { + this.dest = dest; + } + + public void setValues(Map values) { + this.values = values; + } + + @XmlElement + public Map getValues() { + return values; + } +} diff --git a/data/undertestsrc/java/depends/format/json/JDataBuilder.java b/data/undertestsrc/java/depends/format/json/JDataBuilder.java new file mode 100644 index 0000000..7600450 --- /dev/null +++ b/data/undertestsrc/java/depends/format/json/JDataBuilder.java @@ -0,0 +1,49 @@ +package depends.format.json; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; + +import depends.format.FileAttributes; +import depends.matrix.DependencyMatrix; +import depends.matrix.DependencyPair; +import depends.matrix.DependencyValue; + +public class JDataBuilder { + public JDepObject build(DependencyMatrix dependencyMatrix, FileAttributes attribute) { + ArrayList files = dependencyMatrix.getNodes(); + Collection dependencyPairs = dependencyMatrix.getDependencyPairs(); + ArrayList cellObjects = buildCellObjects(dependencyPairs); // transform finalRes into cellObjects + + JDepObject depObject = new JDepObject(); + depObject.setVariables(files); + depObject.setName(attribute.getAttributeName()); + depObject.setSchemaVersion(attribute.getSchemaVersion()); + depObject.setCells(cellObjects); + + return depObject; + } + + private ArrayList buildCellObjects(Collection dependencyPairs) { + ArrayList cellObjects = new ArrayList(); + + for (DependencyPair dependencyPair : dependencyPairs) { + Map valueObject = buildValueObject(dependencyPair.getDependencies()); + JCellObject cellObject = new JCellObject(); + cellObject.setSrc(dependencyPair.getFrom()); + cellObject.setDest(dependencyPair.getTo()); + cellObject.setValues(valueObject); + cellObjects.add(cellObject); + } + return cellObjects; + } + + private Map buildValueObject(Collection dependencies) { + Map valueObject = new HashMap(); + for (DependencyValue dependency : dependencies) { + valueObject.put(dependency.getType(), (float) dependency.getWeight()); + } + return valueObject; + } +} diff --git a/data/undertestsrc/java/depends/format/json/JDepObject.java b/data/undertestsrc/java/depends/format/json/JDepObject.java new file mode 100644 index 0000000..dc5e545 --- /dev/null +++ b/data/undertestsrc/java/depends/format/json/JDepObject.java @@ -0,0 +1,50 @@ +package depends.format.json; + +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; +import java.util.ArrayList; + +@XmlRootElement(name = "matrix") +public class JDepObject { + private String schemaVersion; + private String name; + private ArrayList variables; + private ArrayList cells; + + public String getName() { + return name; + } + + @XmlAttribute(name = "name") + public void setName(String name) { + this.name = name; + } + + public String getSchemaVersion() { + return schemaVersion; + } + + @XmlAttribute(name = "schema-version") + public void setSchemaVersion(String schemaVersion) { + this.schemaVersion = schemaVersion; + } + + public ArrayList getVariables() { + return variables; + } + + @XmlElement + public void setVariables(ArrayList variables) { + this.variables = variables; + } + + public ArrayList getCells() { + return cells; + } + + @XmlElement + public void setCells(ArrayList cells) { + this.cells = cells; + } +} diff --git a/data/undertestsrc/java/depends/format/json/JsonFormatDependencyDumper.java b/data/undertestsrc/java/depends/format/json/JsonFormatDependencyDumper.java new file mode 100644 index 0000000..0171b1d --- /dev/null +++ b/data/undertestsrc/java/depends/format/json/JsonFormatDependencyDumper.java @@ -0,0 +1,41 @@ +package depends.format.json; + +import java.io.File; + +import com.fasterxml.jackson.databind.ObjectMapper; + +import depends.format.AbstractFormatDependencyDumper; +import depends.format.FileAttributes; +import depends.matrix.DependencyMatrix; + +public class JsonFormatDependencyDumper extends AbstractFormatDependencyDumper { + @Override + public String getFormatName() { + return "json"; + } + + public JsonFormatDependencyDumper(DependencyMatrix dependencyMatrix, String projectName, String outputDir) { + super(dependencyMatrix, projectName,outputDir); + } + + @Override + public boolean output() { + JDataBuilder jBuilder = new JDataBuilder(); + JDepObject jDepObject = jBuilder.build(matrix, new FileAttributes(name)); + toJson(jDepObject, composeFilename()+ ".json"); + return true; + } + + + + private void toJson(JDepObject depObject, String jsonFileName) { + ObjectMapper mapper = new ObjectMapper(); + try { + mapper.writerWithDefaultPrettyPrinter().writeValue(new File(jsonFileName), depObject); + } catch (Exception e) { + e.printStackTrace(); + } + + } + +} diff --git a/data/undertestsrc/java/depends/format/path/DotPathFilenameWritter.java b/data/undertestsrc/java/depends/format/path/DotPathFilenameWritter.java new file mode 100644 index 0000000..b2e70d3 --- /dev/null +++ b/data/undertestsrc/java/depends/format/path/DotPathFilenameWritter.java @@ -0,0 +1,26 @@ +package depends.format.path; + +import java.io.File; + +import org.apache.commons.io.FilenameUtils; + +import depends.matrix.FilenameWritter; + +public class DotPathFilenameWritter implements FilenameWritter { + @Override + public String reWrite(String originalPath) { + String ext = FilenameUtils.getExtension(originalPath); + String path = replaceExt(originalPath,ext); + path = path.replace('/', '.'); + path = path.replace('\\', '.'); + return path; + } + + private String replaceExt(String path, String ext) { + if (ext==null) return path; + if (ext.length()==0) return path; + if (!path.endsWith(ext)) return path; + path = path.substring(0,path.length()-ext.length()-1) + "_" + ext; + return path; + } +} diff --git a/data/undertestsrc/java/depends/format/path/EmptyFilenameWritter.java b/data/undertestsrc/java/depends/format/path/EmptyFilenameWritter.java new file mode 100644 index 0000000..89b0131 --- /dev/null +++ b/data/undertestsrc/java/depends/format/path/EmptyFilenameWritter.java @@ -0,0 +1,10 @@ +package depends.format.path; + +import depends.matrix.FilenameWritter; + +public class EmptyFilenameWritter implements FilenameWritter { + @Override + public String reWrite(String originalPath) { + return originalPath; + } +} diff --git a/data/undertestsrc/java/depends/format/xml/XCell.java b/data/undertestsrc/java/depends/format/xml/XCell.java new file mode 100644 index 0000000..320a2b1 --- /dev/null +++ b/data/undertestsrc/java/depends/format/xml/XCell.java @@ -0,0 +1,38 @@ +package depends.format.xml; + +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlElement; +import java.util.ArrayList; + +public class XCell { + private int src; + private int dest; + private ArrayList depends; + + @XmlAttribute(name = "src") + public void setSrc(int src) { + this.src = src; + } + + public int getSrc() { + return src; + } + + @XmlAttribute(name = "dest") + public void setDest(int dest) { + this.dest = dest; + } + + public int getDest() { + return dest; + } + + @XmlElement(name = "depend") + public void setDepends(ArrayList depends) { + this.depends = depends; + } + + public ArrayList getDepends() { + return depends; + } +} diff --git a/data/undertestsrc/java/depends/format/xml/XCells.java b/data/undertestsrc/java/depends/format/xml/XCells.java new file mode 100644 index 0000000..ae6ca77 --- /dev/null +++ b/data/undertestsrc/java/depends/format/xml/XCells.java @@ -0,0 +1,17 @@ +package depends.format.xml; + +import javax.xml.bind.annotation.XmlElement; +import java.util.ArrayList; + +public class XCells { + private ArrayList cells; + + @XmlElement(name = "cell") + public void setCells(ArrayList cells) { + this.cells = cells; + } + + public ArrayList getCells() { + return cells; + } +} diff --git a/data/undertestsrc/java/depends/format/xml/XDataBuilder.java b/data/undertestsrc/java/depends/format/xml/XDataBuilder.java new file mode 100644 index 0000000..869b915 --- /dev/null +++ b/data/undertestsrc/java/depends/format/xml/XDataBuilder.java @@ -0,0 +1,58 @@ +package depends.format.xml; + +import java.util.ArrayList; +import java.util.Collection; + +import depends.format.FileAttributes; +import depends.matrix.DependencyMatrix; +import depends.matrix.DependencyPair; +import depends.matrix.DependencyValue; + +public class XDataBuilder { + public XDepObject build(DependencyMatrix matrix,FileAttributes attribute) { + ArrayList files = matrix.getNodes(); + Collection dependencyPairs = matrix.getDependencyPairs(); + + XFiles xFiles = new XFiles(); + xFiles.setFiles(files); + + ArrayList xCellList = buildCellList(dependencyPairs); + + XCells xCells = new XCells(); + xCells.setCells(xCellList); + + XDepObject xDepObject = new XDepObject(); + xDepObject.setName(attribute.getAttributeName()); + xDepObject.setSchemaVersion(attribute.getSchemaVersion()); + xDepObject.setVariables(xFiles); + xDepObject.setCells(xCells); + + return xDepObject; + } + + + private ArrayList buildCellList(Collection dependencyPairs) { + ArrayList cellList = new ArrayList(); + for (DependencyPair pair : dependencyPairs) { + ArrayList xDepends = buildDependList(pair.getDependencies()); + XCell xCell = new XCell(); + xCell.setSrc(pair.getFrom()); + xCell.setDest(pair.getTo()); + xCell.setDepends(xDepends); + cellList.add(xCell); + } + return cellList; + } + + private ArrayList buildDependList(Collection dependencies) { + ArrayList dependList = new ArrayList(); + + for (DependencyValue dependency : dependencies) { + XDepend xDepend = new XDepend(); + xDepend.setWeight(dependency.getWeight()); + xDepend.setName(dependency.getType()); + dependList.add(xDepend); + } + return dependList; + } +} diff --git a/data/undertestsrc/java/depends/format/xml/XDepObject.java b/data/undertestsrc/java/depends/format/xml/XDepObject.java new file mode 100644 index 0000000..9b37091 --- /dev/null +++ b/data/undertestsrc/java/depends/format/xml/XDepObject.java @@ -0,0 +1,65 @@ +package depends.format.xml; + +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlType; + + +@XmlRootElement(name = "matrix") +@XmlType(propOrder = {"variables", "cells"}) +public class XDepObject { + private String schemaVersion; + private String name; + private XFiles variables; + private XCells cells; + private String xmlns="http://dv8.archdia.com/xml/matrix"; + + public String getName() { + return name; + } + + @XmlAttribute(name = "name") + public void setName(String name) { + this.name = name; + } + + public String getSchemaVersion() { + return schemaVersion; + } + + @XmlAttribute(name = "schema-version") + public void setSchemaVersion(String schemaVersion) { + this.schemaVersion = schemaVersion; + } + + @XmlElement(name = "variables") + public void setVariables(XFiles variables) { + this.variables = variables; + } + + public XFiles getVariables() { + return variables; + } + + @XmlElement(name = "cells") + public void setCells(XCells cells) { + this.cells = cells; + } + + public XCells getCells() { + return cells; + } + + + + + public String getXmlns() { + return xmlns; + } + + @XmlAttribute(name = "xmlns") + public void setXmlns(String xmlns) { + this.xmlns = xmlns; + } +} diff --git a/data/undertestsrc/java/depends/format/xml/XDepend.java b/data/undertestsrc/java/depends/format/xml/XDepend.java new file mode 100644 index 0000000..94ff1fd --- /dev/null +++ b/data/undertestsrc/java/depends/format/xml/XDepend.java @@ -0,0 +1,30 @@ +package depends.format.xml; + +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlRootElement; + +@XmlRootElement(name = "depend") +public class XDepend { + + private String name; + + private float weight; + + public String getName() { + return name; + } + + @XmlAttribute(name = "name") + public void setName(String name) { + this.name = name; + } + + public float getWeight() { + return weight; + } + + @XmlAttribute(name = "weight") + public void setWeight(float weight) { + this.weight = weight; + } +} diff --git a/data/undertestsrc/java/depends/format/xml/XFiles.java b/data/undertestsrc/java/depends/format/xml/XFiles.java new file mode 100644 index 0000000..8cb7ff9 --- /dev/null +++ b/data/undertestsrc/java/depends/format/xml/XFiles.java @@ -0,0 +1,18 @@ +package depends.format.xml; + +import javax.xml.bind.annotation.XmlElement; +import java.util.ArrayList; + +public class XFiles { + + private ArrayList files; + + public ArrayList getFiles() { + return files; + } + + @XmlElement(name = "variable") + public void setFiles(ArrayList files) { + this.files = files; + } +} diff --git a/data/undertestsrc/java/depends/format/xml/XmlFormatDependencyDumper.java b/data/undertestsrc/java/depends/format/xml/XmlFormatDependencyDumper.java new file mode 100644 index 0000000..5638bf9 --- /dev/null +++ b/data/undertestsrc/java/depends/format/xml/XmlFormatDependencyDumper.java @@ -0,0 +1,39 @@ +package depends.format.xml; + +import java.io.FileOutputStream; + +import javax.xml.bind.JAXBContext; +import javax.xml.bind.Marshaller; + +import depends.format.AbstractFormatDependencyDumper; +import depends.format.FileAttributes; +import depends.matrix.DependencyMatrix; + +public class XmlFormatDependencyDumper extends AbstractFormatDependencyDumper{ + @Override + public String getFormatName() { + return "xml"; + } + public XmlFormatDependencyDumper(DependencyMatrix dependencyMatrix, String projectName, String outputDir) { + super(dependencyMatrix,projectName,outputDir); + } + + private void toXml(XDepObject xDepObject, String xmlFileName) { + try { + JAXBContext jaxbContext = JAXBContext.newInstance(XDepObject.class); + Marshaller marshaller = jaxbContext.createMarshaller(); + marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); + marshaller.marshal(xDepObject, new FileOutputStream(xmlFileName)); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Override + public boolean output() { + XDataBuilder xBuilder = new XDataBuilder(); + XDepObject xDepObject = xBuilder.build(matrix,new FileAttributes(name)); + toXml(xDepObject,composeFilename()+".xml"); + return true; + } +} diff --git a/data/undertestsrc/java/depends/importtypes/ExactMatchImport.java b/data/undertestsrc/java/depends/importtypes/ExactMatchImport.java new file mode 100644 index 0000000..219ac46 --- /dev/null +++ b/data/undertestsrc/java/depends/importtypes/ExactMatchImport.java @@ -0,0 +1,7 @@ +package depends.importtypes; + +public class ExactMatchImport extends Import{ + public ExactMatchImport(String content) { + super(content); + } +} diff --git a/data/undertestsrc/java/depends/importtypes/FileImport.java b/data/undertestsrc/java/depends/importtypes/FileImport.java new file mode 100644 index 0000000..c47d5cb --- /dev/null +++ b/data/undertestsrc/java/depends/importtypes/FileImport.java @@ -0,0 +1,7 @@ +package depends.importtypes; + +public class FileImport extends Import{ + public FileImport(String content) { + super(content); + } +} diff --git a/data/undertestsrc/java/depends/importtypes/Import.java b/data/undertestsrc/java/depends/importtypes/Import.java new file mode 100644 index 0000000..ac40d03 --- /dev/null +++ b/data/undertestsrc/java/depends/importtypes/Import.java @@ -0,0 +1,11 @@ +package depends.importtypes; + +public abstract class Import { + private String content; + public String getContent() { + return content; + } + public Import(String content) { + this.content = content; + } +} diff --git a/data/undertestsrc/java/depends/importtypes/PackageWildCardImport.java b/data/undertestsrc/java/depends/importtypes/PackageWildCardImport.java new file mode 100644 index 0000000..b70887d --- /dev/null +++ b/data/undertestsrc/java/depends/importtypes/PackageWildCardImport.java @@ -0,0 +1,7 @@ +package depends.importtypes; + +public class PackageWildCardImport extends Import{ + public PackageWildCardImport(String content) { + super(content); + } +} diff --git a/data/undertestsrc/java/depends/matrix/DependencyGenerator.java b/data/undertestsrc/java/depends/matrix/DependencyGenerator.java new file mode 100644 index 0000000..aabae20 --- /dev/null +++ b/data/undertestsrc/java/depends/matrix/DependencyGenerator.java @@ -0,0 +1,7 @@ +package depends.matrix; + +import depends.entity.repo.EntityRepo; + +public interface DependencyGenerator { + DependencyMatrix build(EntityRepo entityRepo); +} diff --git a/data/undertestsrc/java/depends/matrix/DependencyMatrix.java b/data/undertestsrc/java/depends/matrix/DependencyMatrix.java new file mode 100644 index 0000000..692bde4 --- /dev/null +++ b/data/undertestsrc/java/depends/matrix/DependencyMatrix.java @@ -0,0 +1,86 @@ +package depends.matrix; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Comparator; +import java.util.HashMap; + +import depends.entity.Entity; +import depends.entity.repo.EntityRepo; + +public class DependencyMatrix { + private HashMap dependencyPairs = new HashMap<>(); + private ArrayList nodes; + private ArrayList reMappedNodes; + private Integer relationCount=0; + public DependencyMatrix() { + } + + public Collection getDependencyPairs() { + return dependencyPairs.values(); + } + + public void addDependency(String depType, Integer from, Integer to, Entity fromEntity, Entity toEntity) { + if(from.equals(to) || from == -1 || to == -1) { + return; + } + if (dependencyPairs.get(DependencyPair.key(from,to))==null) { + dependencyPairs.put(DependencyPair.key(from,to),new DependencyPair(from,to)); + } + DependencyPair dependencyPair = dependencyPairs.get(DependencyPair.key(from,to)); + dependencyPair.addDependency(depType,fromEntity, toEntity); + relationCount++; + } + + public ArrayList getNodes() { + return reMappedNodes; + } + + public void setNodes(ArrayList nodes) { + this.nodes = nodes; + } + + + private Integer translateToNewId(EntityRepo repo, HashMap nodesMap, Integer key) { + return nodesMap.get(repo.getEntity(key).getDisplayName()); + } + + public void remapIds(EntityRepo repo) { + HashMap nodesMap = new HashMap<>(); + reMappedNodes = new ArrayList<>(nodes); + reMappedNodes.sort(new Comparator() { + @Override + public int compare(String o1, String o2) { + return o1.compareTo(o2); + } + }); + + for (int i=0;i dependencies; + public DependencyPair(Integer from, Integer to) { + this.from = from; + this.to= to; + dependencies = new HashMap<>(); + } + public static String key(Integer from, Integer to) { + return ""+from+"-->"+to; + } + public void addDependency(String depType, Entity fromEntity, Entity toEntity) { + if (dependencies.get(depType)==null) + dependencies.put(depType, new DependencyValue(depType)); + DependencyValue value = dependencies.get(depType); + value.addDependency(fromEntity, toEntity); + } + public Integer getFrom() { + return from; + } + public Integer getTo() { + return to; + } + public Collection getDependencies() { + return dependencies.values(); + } + public void reMap(Integer from, Integer to) { + this.from = from; + this.to = to; + } +} diff --git a/data/undertestsrc/java/depends/matrix/DependencyValue.java b/data/undertestsrc/java/depends/matrix/DependencyValue.java new file mode 100644 index 0000000..9e0bc83 --- /dev/null +++ b/data/undertestsrc/java/depends/matrix/DependencyValue.java @@ -0,0 +1,33 @@ +package depends.matrix; + +import depends.entity.Entity; + +public class DependencyValue{ + private int weight; + private String type; + private StringBuffer dependencyDetail; + public DependencyValue(String type) { + this.type = type; + this.weight=0; + dependencyDetail = new StringBuffer(); + } + + public void addDependency(Entity from, Entity to) { + this.weight++; + dependencyDetail.append("[").append(type).append("]") + .append(from.getQualifiedName()).append("->").append(to.getQualifiedName()) + .append("\n"); + } + + public int getWeight() { + return weight; + } + + public String getType() { + return type; + } + + public String getDetails() { + return dependencyDetail.toString(); + } +} \ No newline at end of file diff --git a/data/undertestsrc/java/depends/matrix/FileDependencyGenerator.java b/data/undertestsrc/java/depends/matrix/FileDependencyGenerator.java new file mode 100644 index 0000000..49ba612 --- /dev/null +++ b/data/undertestsrc/java/depends/matrix/FileDependencyGenerator.java @@ -0,0 +1,45 @@ +package depends.matrix; + +import java.util.ArrayList; + +import depends.entity.Entity; +import depends.entity.FileEntity; +import depends.entity.repo.EntityRepo; +import depends.relations.Relation; + +public class FileDependencyGenerator implements DependencyGenerator{ + /** + * Build the dependency matrix (without re-mapping file id) + * @param entityRepo which contains entities and relations + * @return the generated dependency matrix + */ + @Override + public DependencyMatrix build(EntityRepo entityRepo) { + DependencyMatrix dependencyMatrix = new DependencyMatrix(); + ArrayList files = new ArrayList(); + for (Entity entity:entityRepo.getEntities()) { + if (entity instanceof FileEntity){ + files.add( entity.getDisplayName()); + } + int fileEntityFrom = getFileEntityIdNoException(entityRepo, entity); + if (fileEntityFrom==-1) continue; + for (Relation relation:entity.getRelations()) { + if (relation.getEntity().getId()>=0) { + int fileEntityTo = getFileEntityIdNoException(entityRepo,relation.getEntity()); + if (fileEntityTo==-1) continue; + dependencyMatrix.addDependency(relation.getType(), fileEntityFrom,fileEntityTo,entity,relation.getEntity()); + } + } + } + dependencyMatrix.setNodes(files); + return dependencyMatrix; + } + + + private int getFileEntityIdNoException(EntityRepo entityRepo, Entity entity) { + Entity ancestor = entity.getAncestorOfType(FileEntity.class); + if (ancestor==null) + return -1; + return ancestor.getId(); + } +} diff --git a/data/undertestsrc/java/depends/matrix/FilenameWritter.java b/data/undertestsrc/java/depends/matrix/FilenameWritter.java new file mode 100644 index 0000000..5659191 --- /dev/null +++ b/data/undertestsrc/java/depends/matrix/FilenameWritter.java @@ -0,0 +1,5 @@ +package depends.matrix; + +public interface FilenameWritter { + String reWrite(String originalPath); +} diff --git a/data/undertestsrc/java/depends/matrix/FunctionDependencyGenerator.java b/data/undertestsrc/java/depends/matrix/FunctionDependencyGenerator.java new file mode 100644 index 0000000..93bafed --- /dev/null +++ b/data/undertestsrc/java/depends/matrix/FunctionDependencyGenerator.java @@ -0,0 +1,50 @@ +package depends.matrix; + +import java.util.ArrayList; + +import depends.entity.Entity; +import depends.entity.FileEntity; +import depends.entity.FunctionEntity; +import depends.entity.repo.EntityRepo; +import depends.relations.Relation; + +public class FunctionDependencyGenerator implements DependencyGenerator { + @Override + public DependencyMatrix build(EntityRepo entityRepo) { + DependencyMatrix dependencyMatrix = new DependencyMatrix(); + ArrayList elements = new ArrayList(); + for (Entity entity : entityRepo.getEntities()) { + if (entity instanceof FunctionEntity) { + elements.add(entity.getDisplayName()); + } + int fileEntityFrom = getFunctionEntityIdNoException(entity); + if (fileEntityFrom == -1) + continue; + for (Relation relation : entity.getRelations()) { + if (relation.getEntity().getId() >= 0) { + int fileEntityTo = getFunctionEntityIdNoException(relation.getEntity()); + if (fileEntityTo == -1) + continue; + dependencyMatrix.addDependency(relation.getType(), fileEntityFrom, fileEntityTo, entity, + relation.getEntity()); + } + } + } + dependencyMatrix.setNodes(elements); + return dependencyMatrix; + } + + private String getFileNameNoException(Entity entity) { + Entity ancestor = entity.getAncestorOfType(FileEntity.class); + if (ancestor == null) + return ""; + return ancestor.getRawName(); + } + + private int getFunctionEntityIdNoException(Entity entity) { + Entity ancestor = entity.getAncestorOfType(FunctionEntity.class); + if (ancestor == null) + return -1; + return ancestor.getId(); + } +} diff --git a/data/undertestsrc/java/depends/relations/ImportLookupStrategy.java b/data/undertestsrc/java/depends/relations/ImportLookupStrategy.java new file mode 100644 index 0000000..abe4795 --- /dev/null +++ b/data/undertestsrc/java/depends/relations/ImportLookupStrategy.java @@ -0,0 +1,15 @@ +package depends.relations; + +import java.util.List; + +import depends.entity.Entity; +import depends.entity.FileEntity; +import depends.entity.repo.EntityRepo; +import depends.importtypes.Import; + +public interface ImportLookupStrategy { + Entity lookupImportedType(String name, FileEntity fileEntity, EntityRepo repo, Inferer inferer); + List getImportedRelationEntities(List importedNames, EntityRepo repo); + List getImportedTypes(List importedNames, EntityRepo repo); + List getImportedFiles(List importedNames, EntityRepo repo); +} diff --git a/data/undertestsrc/java/depends/relations/Inferer.java b/data/undertestsrc/java/depends/relations/Inferer.java new file mode 100644 index 0000000..c2eff0b --- /dev/null +++ b/data/undertestsrc/java/depends/relations/Inferer.java @@ -0,0 +1,258 @@ +package depends.relations; + +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import depends.entity.ContainerEntity; +import depends.entity.Entity; +import depends.entity.FileEntity; +import depends.entity.MultiDeclareEntities; +import depends.entity.TypeEntity; +import depends.entity.repo.BuiltInType; +import depends.entity.repo.EntityRepo; +import depends.entity.repo.NullBuiltInType; +import depends.importtypes.Import; + +public class Inferer { + private static final Logger logger = LoggerFactory.getLogger(Inferer.class); + + static final public TypeEntity buildInType = new TypeEntity("built-in", null, -1); + static final public TypeEntity externalType = new TypeEntity("external", null, -1); + static final public TypeEntity genericParameterType = new TypeEntity("T", null, -1); + private BuiltInType buildInTypeManager = new NullBuiltInType(); + private ImportLookupStrategy importLookupStrategy; + private HashSet unsolvedSymbols; + private EntityRepo repo; + + public Inferer(EntityRepo repo, ImportLookupStrategy importLookupStrategy, BuiltInType buildInTypeManager) { + this.repo = repo; + this.importLookupStrategy = importLookupStrategy; + this.buildInTypeManager = buildInTypeManager; + unsolvedSymbols= new HashSet<>(); + } + + /** + * Resolve all bindings + * - Firstly, we resolve all types from there names. + * - Secondly, we resolve all expressions (expression will use type infomation of previous step + */ + public Set resolveAllBindings() { + resolveTypes(); + resolveExpressoins(); + System.out.println("Dependency analaysing...."); + new RelationCounter(repo.getEntities()).computeRelations(); + System.out.println("Dependency done...."); + return unsolvedSymbols; + } + + private void resolveTypes() { + for (Entity entity:repo.getEntities()) { + if (!(entity instanceof FileEntity)) continue; + entity.inferEntities(this); + } + } + private void resolveExpressoins() { + for (Entity entity:repo.getEntities()) { + if ((entity instanceof ContainerEntity)) + ((ContainerEntity)entity).resolveExpressions(this); + } + } + + /** + * For types start with the prefix, it will be treated as built-in type + * For example, java.io.* in Java, or __ in C/C++ + * @param prefix + * @return + */ + public boolean isBuiltInTypePrefix(String prefix) { + return buildInTypeManager.isBuiltInTypePrefix(prefix); + } + + /** + * Different languages have different strategy on how to compute the imported types + * and the imported files. + * For example, in C/C++, both imported types (using namespace, using ) and imported files exists. + * while in java, only 'import class/function, or import wildcard class.* package.* exists. + */ + public List getImportedRelationEntities(List importedNames) { + return importLookupStrategy.getImportedRelationEntities(importedNames, repo); + } + + public List getImportedTypes(List importedNames) { + return importLookupStrategy.getImportedTypes(importedNames, repo); + } + + public List getImportedFiles(List importedNames) { + return importLookupStrategy.getImportedFiles(importedNames, repo); + } + + /** + * By given raw name, to infer the type of the name + * for example + * if it is a class, the class is the type + * if it is a function, the return type is the type + * if it is a variable, type of variable is the type + * @param fromEntity + * @param rawName + * @return + */ + public TypeEntity inferTypeFromName(Entity fromEntity, String rawName) { + Entity data = resolveName(fromEntity, rawName, true); + if (data == null) + return null; + return data.getType(); + } + + /** + * By given raw name, to infer the entity of the name + * @param fromEntity + * @param rawName + * @param searchImport + * @return + */ + public Entity resolveName(Entity fromEntity, String rawName, boolean searchImport) { + Entity entity = resolveNameInternal(fromEntity,rawName,searchImport); + if (logger.isDebugEnabled()) { + logger.debug("resolve name " + rawName + " from " + fromEntity.getQualifiedName() +" ==> " + + (entity==null?"null":entity.getQualifiedName())); + } + return entity; + } + + private Entity resolveNameInternal(Entity fromEntity, String rawName, boolean searchImport) { + if (rawName == null) + return null; + if (buildInTypeManager.isBuiltInType(rawName)) { + return buildInType; + } + if (buildInTypeManager.isBuiltInTypePrefix(rawName)) { + return buildInType; + } + + // qualified name will first try global name directly + if (rawName.contains(".")) { + if (repo.getEntity(rawName) != null) + return repo.getEntity(rawName); + } + + // first we lookup the first symbol + String[] names = rawName.split("\\."); + if (names.length == 0) + return null; + Entity type = lookupEntity(fromEntity, names[0], searchImport); + if (type == null) + return null; + if (names.length == 1) { + return type; + } + // then find the subsequent symbols + return findEntitySince(type, names, 1); + } + + private Entity lookupEntity(Entity fromEntity, String name, boolean searcImport) { + if (name.equals("this") || name.equals("class")) { + TypeEntity entityType = (TypeEntity) (fromEntity.getAncestorOfType(TypeEntity.class)); + return entityType; + } else if (name.equals("super")) { + TypeEntity parent = (TypeEntity) (fromEntity.getAncestorOfType(TypeEntity.class)); + if (parent != null) { + TypeEntity parentType = parent.getInheritedType(); + if (parentType!=null) + return parentType; + } + } + + Entity inferData = findEntityUnderSamePackage(fromEntity, name); + if (inferData != null) + return inferData; + if (searcImport) + inferData = lookupTypeInImported((FileEntity)(fromEntity.getAncestorOfType(FileEntity.class)), name); + return inferData; + } + /** + * To lookup entity in case of a.b.c from a; + * @param precendenceEntity + * @param names + * @param nameIndex + * @return + */ + private Entity findEntitySince(Entity precendenceEntity, String[] names, int nameIndex) { + if (nameIndex >= names.length) { + return precendenceEntity; + } + //If it is not an entity with types (not a type, var, function), fall back to itself + if (precendenceEntity.getType()==null) + return precendenceEntity; + + for (Entity child : precendenceEntity.getType().getChildren()) { + if (child.getRawName().equals(names[nameIndex])) { + return findEntitySince(child, names, nameIndex + 1); + } + } + return null; + } + + private Entity lookupTypeInImported(FileEntity fileEntity, String name) { + if (fileEntity == null) + return null; + Entity type = importLookupStrategy.lookupImportedType(name, fileEntity, repo,this); + if (type != null) + return type; + return externalType; + } + + + /** + * In Java/C++ etc, the same package names should take priority of resolving. + * the entity lookup is implemented recursively. + * @param fromEntity + * @param name + * @return + */ + private Entity findEntityUnderSamePackage(Entity fromEntity, String name) { + while (true) { + Entity entity = tryToFindEntityWithName(fromEntity, name); + if (entity != null) + return entity; + for (Entity child : fromEntity.getChildren()) { + entity = tryToFindEntityWithName(child, name); + if (entity != null) + return entity; + if (child instanceof FileEntity) { + for (Entity classUnderFile : child.getChildren()) { + entity = tryToFindEntityWithName(classUnderFile, name); + if (entity != null) + return entity; + } + } + } + fromEntity = fromEntity.getParent(); + if (fromEntity == null) + break; + } + return null; + } + + /** + * Only used by findEntityUnderSamePackage + * @param fromEntity + * @param name + * @return + */ + private Entity tryToFindEntityWithName(Entity fromEntity, String name) { + if (!fromEntity.getRawName().equals(name)) + return null; + if (fromEntity instanceof MultiDeclareEntities) { + for (Entity declaredEntitiy : ((MultiDeclareEntities) fromEntity).getEntities()) { + if (declaredEntitiy.getRawName().equals(name) && declaredEntitiy instanceof TypeEntity) { + return declaredEntitiy; + } + } + } + return fromEntity; + } +} diff --git a/data/undertestsrc/java/depends/relations/Relation.java b/data/undertestsrc/java/depends/relations/Relation.java new file mode 100644 index 0000000..311be28 --- /dev/null +++ b/data/undertestsrc/java/depends/relations/Relation.java @@ -0,0 +1,28 @@ +package depends.relations; + +import depends.entity.Entity; + +/** + * Dependency relation object + */ +public class Relation { + private String type; + private Entity toEntity; + + public Relation(String type, Entity toEntity) { + this.toEntity = toEntity; + this.type = type; + } + public String getType() { + return type; + } + + @Override + public String toString() { + return "Relation[" + type + "]-->" + toEntity.getId() + "(" + toEntity.getQualifiedName() + ")"; + } + public Entity getEntity() { + return toEntity; + } + +} diff --git a/data/undertestsrc/java/depends/relations/RelationCounter.java b/data/undertestsrc/java/depends/relations/RelationCounter.java new file mode 100644 index 0000000..510b918 --- /dev/null +++ b/data/undertestsrc/java/depends/relations/RelationCounter.java @@ -0,0 +1,118 @@ +package depends.relations; + +import java.util.Collection; +import java.util.HashSet; +import java.util.List; + +import depends.deptypes.DependencyType; +import depends.entity.ContainerEntity; +import depends.entity.Entity; +import depends.entity.Expression; +import depends.entity.FileEntity; +import depends.entity.FunctionEntity; +import depends.entity.TypeEntity; +import depends.entity.VarEntity; + +public class RelationCounter { + + private Collection entities; + + public RelationCounter(Collection entities) { + this.entities = entities; + } + + public void computeRelations() { + for (Entity entity:entities) { + if (entity instanceof FileEntity) { + computeImports((FileEntity)entity); + } + if (entity instanceof FunctionEntity) { + computeFunctionRelations((FunctionEntity)entity); + } + if (entity instanceof TypeEntity) { + computeTypeRelations((TypeEntity)entity); + } + if (entity instanceof ContainerEntity) { + computeContainerRelations((ContainerEntity)entity); + } + } + } + + + private void computeContainerRelations(ContainerEntity entity) { + for (VarEntity var:entity.getVars()) { + if (var.getType()!=null) + entity.addRelation(new Relation(DependencyType.CONTAIN,var.getType())); + } + for (TypeEntity type:entity.getResolvedAnnotations()) { + entity.addRelation(new Relation(DependencyType.USE,type)); + } + for (TypeEntity type:entity.getResolvedTypeParameters()) { + entity.addRelation(new Relation(DependencyType.USE,type)); + } + + HashSet usedEntities = new HashSet<>(); + for (Expression expression:entity.expressions().values()){ + Entity referredEntity = expression.getReferredEntity(); + if (referredEntity==null) { + continue; + } + + if (expression.isCall) { + entity.addRelation(new Relation(DependencyType.CALL,referredEntity)); + } + if (expression.isCreate) { + entity.addRelation(new Relation(DependencyType.CREATE,referredEntity)); + } + if (expression.isSet) { //SET is merged with USE + entity.addRelation(new Relation(DependencyType.USE,referredEntity)); + } + if (expression.isCast) { + entity.addRelation(new Relation(DependencyType.CAST,referredEntity)); + } + if (!expression.isCall && !expression.isCreate && !expression.isCast) { + usedEntities.add(expression.getReferredEntity()); + } + } + + for (Entity usedEntity:usedEntities) { + entity.addRelation(new Relation(DependencyType.USE,usedEntity)); + } + } + + private void computeTypeRelations(TypeEntity type) { + for (TypeEntity superType:type.getInheritedTypes()) { + type.addRelation(new Relation(DependencyType.INHERIT,superType)); + } + for (TypeEntity interfaceType:type.getImplementedTypes()) { + type.addRelation(new Relation(DependencyType.IMPLEMENT,interfaceType)); + } + } + + private void computeFunctionRelations(FunctionEntity func) { + for (TypeEntity returnType:func.getReturnTypes()) { + func.addRelation(new Relation(DependencyType.RETURN,returnType)); + } + for (VarEntity parameter:func.getParameters()) { + if (parameter.getType()!=null) + func.addRelation(new Relation(DependencyType.PARAMETER,parameter.getType())); + } + for (TypeEntity throwType:func.getThrowTypes()) { + func.addRelation(new Relation(DependencyType.THROW,throwType)); + } + } + + private void computeImports(FileEntity file) { + List imports = file.getImportedRelationEntities(); + for (Entity imported:imports) { + if (imported instanceof FileEntity) + { + if (((FileEntity)imported).isInProjectScope()) + file.addRelation(new Relation(DependencyType.IMPORT,imported)); + }else { + file.addRelation(new Relation(DependencyType.IMPORT,imported)); + } + } + } + +} diff --git a/data/undertestsrc/java/depends/util/FileTraversal.java b/data/undertestsrc/java/depends/util/FileTraversal.java new file mode 100644 index 0000000..cc1adfc --- /dev/null +++ b/data/undertestsrc/java/depends/util/FileTraversal.java @@ -0,0 +1,68 @@ +package depends.util; + +import java.io.File; +import java.util.ArrayList; + +/** + * Recursively visit every file in the given root path using the + * extended IFileVisitor + * + */ +public class FileTraversal { + /** + * The visitor interface + * Detail operation should be implemented here + */ + public interface IFileVisitor { + void visit(File file); + } + + IFileVisitor visitor; + private ArrayList extensionFilters = new ArrayList<>(); + public FileTraversal(IFileVisitor visitor){ + this.visitor = visitor; + } + + public void travers(String path) { + File dir = new File(path); + travers(dir); + } + + public void travers(File root) { + File[] files = root.listFiles(); + + if (files == null) + return; + for (int i = 0; i < files.length; i++) { + if (files[i].isDirectory()) { + travers(files[i]); + } else { + File f = files[i]; + invokeVisitor(f); + } + } + } + + private void invokeVisitor(File f) { + if (extensionFilters.size()==0) { + visitor.visit(f); + }else { + for (String ext:extensionFilters) { + if (f.getAbsolutePath().toLowerCase().endsWith(ext.toLowerCase())) { + visitor.visit(f); + } + } + } + } + + public FileTraversal extensionFilter(String ext) { + this.extensionFilters.add(ext.toLowerCase()); + return this; + } + + public void extensionFilter(String[] fileSuffixes) { + for (String fileSuffix:fileSuffixes){ + extensionFilter(fileSuffix); + } + } +} \ No newline at end of file diff --git a/data/undertestsrc/java/depends/util/FileUtil.java b/data/undertestsrc/java/depends/util/FileUtil.java new file mode 100644 index 0000000..3a1feee --- /dev/null +++ b/data/undertestsrc/java/depends/util/FileUtil.java @@ -0,0 +1,19 @@ +package depends.util; + +import java.io.File; +import java.io.IOException; + +public class FileUtil { + public static String uniqFilePath(String filePath) { + try { + File f = new File(filePath); + filePath = f.getCanonicalPath(); + } catch (IOException e) { + } + return filePath; + } + + public static boolean existFile(String path) { + return new File(path).exists(); + } +} diff --git a/src/main/antlr4/depends/extractor/java/JavaLexer.g4 b/src/main/antlr4/depends/extractor/java/JavaLexer.g4 index 6919d23..f9f0654 100644 --- a/src/main/antlr4/depends/extractor/java/JavaLexer.g4 +++ b/src/main/antlr4/depends/extractor/java/JavaLexer.g4 @@ -142,7 +142,6 @@ BITAND: '&'; BITOR: '|'; CARET: '^'; MOD: '%'; - ADD_ASSIGN: '+='; SUB_ASSIGN: '-='; MUL_ASSIGN: '*='; diff --git a/src/main/antlr4/depends/extractor/ruby/RubyLexer.g4 b/src/main/antlr4/depends/extractor/ruby/RubyLexer.g4 deleted file mode 100644 index a681698..0000000 --- a/src/main/antlr4/depends/extractor/ruby/RubyLexer.g4 +++ /dev/null @@ -1,472 +0,0 @@ -lexer grammar RubyLexer; -@lexer::header{ -import java.util.List; -import java.util.ArrayList; -import java.util.LinkedList; -import java.util.Queue; -} - -@lexer::members{ - - String hereDocSymbol = ""; - String quotedStringStartSymbol = ""; - StringBuilder stringBuffer; - Queue tokenList = new LinkedList<>(); - boolean shouldReleaseBufferedToken = false; - Token next; - boolean isHereDocSymbol(String text){ - String theSym = text.replace("\r","").replace("\n","").replace("\"","").replace("`",""); - hereDocSymbol = hereDocSymbol.replace("\r","").replace("\n","").replace("<<-","").replace("<<","").replace("\"","").replace("`",""); - return theSym.equals(hereDocSymbol); - } - - void startHereDoc(){ - hereDocSymbol = getText(); - stringBuffer = new StringBuilder(); - tokenList = new LinkedList<>(); - shouldReleaseBufferedToken = false; - while(true) { - next = nextToken(); - if (next==null) break; - if (next.getType()==CRLF || - next.getType()==SL_COMMENT) { - break; - } - tokenList.add(next); - } - mode(HERE_DOC_MODE); - skip(); - } - void tryEndHereDoc(){ - if ( isHereDocSymbol(getText())){ - mode(DEFAULT_MODE); - setType(String); - setText(stringBuffer.toString()); - shouldReleaseBufferedToken = true; - }else{ - stringBuffer.append(getText()); - skip(); - } - } - boolean isQuotedPair(String text){ - if (quotedStringStartSymbol.equals("(") && text.equals(")")) return true; - if (quotedStringStartSymbol.equals("[") && text.equals("]")) return true; - if (quotedStringStartSymbol.equals("{") && text.equals("}")) return true; - if (quotedStringStartSymbol.equals("<") && text.equals(">")) return true; - if (quotedStringStartSymbol.equals("|") && text.equals("|")) return true; - if (quotedStringStartSymbol.equals(text)) return true; - return false; - } - - @Override - public Token getToken() { - if (!shouldReleaseBufferedToken) - return super.getToken(); - if (!tokenList.isEmpty()){ - return tokenList.peek(); - } - return super.getToken(); - } - - - @Override - public Token nextToken() { - if (!shouldReleaseBufferedToken) - return super.nextToken(); - if (!tokenList.isEmpty()){ - Token t = tokenList.remove(); - return t; - } - return super.nextToken(); - } - -} - -//HereDoc -HereDoc1: '<<' '-'? Identifier - { - startHereDoc(); - } - ; - -HereDoc2: '<<' '-'? StringFragment - { - startHereDoc(); - } - ; - -HereDoc3: ShellCommandFrag - { - startHereDoc(); - } - ; - -PercentString: '%' [IQRSWXiqrswx] ~[A-Za-z0-9] - { - quotedStringStartSymbol = getText().substring(2); - stringBuffer = new StringBuilder(); - skip(); - mode(QUOTED_STR_MODE); - } - ; - -// Keywords -ALIAS: 'alias'; -BEGIN: 'begin'; -BEGIN_BLOCK: 'BEGIN'; -BREAK: 'break'; -CASE: 'case'; -CLASS: 'class'; -DEF: 'def'; -DEFINED: 'defined?'; -DO: 'do'; -ELSE: 'else'; -ELSIF: 'elsif'; -END_BLOCK: 'END'; -END: 'end'; -ENSURE: 'ensure'; -FALSE: 'false'; -FOR: 'for'; -IF: 'if'; -IN: 'in'; -MODULE: 'module'; -NEXT: 'next'; -NIL: 'nil'; -NOT: 'not'; -RAISE: 'raise'; -REDO: 'redo'; -RESCUE: 'rescue'; -RETRY: 'retry'; -RETURN: 'return'; -SELF: 'self'; -SUPER: 'super'; -THEN: 'then'; -TRUE: 'true'; -UNDEF: 'undef'; -UNLESS: 'unless'; -UNTIL: 'until'; -WHEN: 'when'; -WHILE: 'while'; -YIELD: 'yield'; - -//non-keyword but important -REQUIRE: 'require'; -// Literals - -Integer - : - Sign? Digits ExponentPart? NumberTypeSuffix? - | HEX_LITERAL ExponentPart? NumberTypeSuffix? - | OCT_LITERAL ExponentPart? NumberTypeSuffix? - | DEC_LITERAL ExponentPart? NumberTypeSuffix? - | BINARY_LITERAL ExponentPart? NumberTypeSuffix? -; - - - - -Float -: - Sign? [0-9]* '.' [0-9]+ ExponentPart? NumberTypeSuffix? -; - - - -Regex: - '/' ~( '\n' | '\r' | '/' |' ')+ '/' 'i'? -; -String -: - StringFragment - | SingleCharacterString -; - - -DollarSpecial: - '$' [!?$@;/\\_~&'>*] | - '$' '.' | '\''; - -// Separators -COMMA: ','; -SEMICOLON: ';'; -CRLF: '\r'? '\n'; -COLON: ':'; -DOT: '.'; -LEFT_RBRACKET: '('; -RIGHT_RBRACKET: ')'; -LEFT_SBRACKET: '['; -RIGHT_SBRACKET: ']'; -LEFT_PAREN: '{'; -RIGHT_PAREN: '}'; -DOT2: '..'; -DOT3: '...'; -COLON2: '::'; -ANDDOT: '&.'; -QUESTION: '?'; -// Operators -PLUS: '+'; -MINUS: '-'; -MUL: '*'; -DIV: '/'; -MOD: '%'; -EXP: '**'; -EQUAL: '=='; -EQUAL3: '==='; -PATTERN_MATCH: '=~'; -NOT_EQUAL: '!='; -GREATER: '>'; -LESS: '<'; -LESS_EQUAL: '<='; -GREATER_EQUAL: '>='; -ASSIGN: '='; -ASSOC: '=>'; -PLUS_ASSIGN: '+='; -MINUS_ASSIGN: '-='; -MUL_ASSIGN: '*='; -DIV_ASSIGN: '/='; -BIT_OR_ASSIGN: '|='; -BIT_AND_ASSIGN: '&='; -OR_ASSIGN: '||='; -AND_ASSIGN: '&&='; -MOD_ASSIGN: '%='; -EXP_ASSIGN: '**='; -BIT_AND: '&'; -BIT_OR: '|'; -BIT_XOR: '^'; -BIT_NOT: '~'; -BIT_SHL: '<<'; -BIT_SHR: '>>'; -BIT_XOR_ASSIGN: '^='; -BIT_NOT_ASSIGN: '~='; -BIT_SHL_ASSIGN: '<<='; -BIT_SHR_ASSIGN: '>>='; -AND: 'and' | '&&'; -OR: 'or' | '||'; -SIGH: '!'; -Sign: '+'|'-'; -DOLLAR: '$'; -AT: '@'; -SHARP: '#'; - -//Comments -SL_COMMENT: ('#' ~( '\r' | '\n' )* '\r'? '\n') ; - -ML_COMMENT: ('=begin' .*? '=end' '\r'? '\n') -> skip; - -WS: (' '| '\t')+ -> skip; - -//Identifiers -Identifier: IdentifierFrag; -ShellCommand: ShellCommandFrag; - -// Fragment rules -fragment -HEX_FLOAT_LITERAL -: - '0' [xX] - ( - HexDigits '.'? - | HexDigits? '.' HexDigits - ) [pP] [+-]? Digits [fFdD]? -; - -fragment -HEX_LITERAL -: - '0' [xX] [0-9a-fA-F] - ( - [0-9a-fA-F_]* [0-9a-fA-F] - )? [lL]? -; - -fragment -DEC_LITERAL -: - '0' [Dd]? [0-7] - ( - [0-7_]* [0-7] - )? [lL]? -; - -fragment -OCT_LITERAL -: - '0' [Oo]? '_'* [0-7] - ( - [0-7_]* [0-7] - )? [lL]? -; - -fragment -BINARY_LITERAL -: - '0' [bB] [01] - ( - [01_]* [01] - )? [lL]? -; - -fragment -HexDigits -: - HexDigit - ( - ( - HexDigit - | '_' - )* HexDigit - )? -; - -fragment -HexDigit -: - [0-9a-fA-F] -; - -fragment -ESCAPED_QUOTE -: - '\\"' - | '\\\'' -; - -fragment -Digits -: - [0-9] - ( - [0-9_]* [0-9] - )? -; - -/* i means imaginary(complex) number, r means a rational number */ -fragment -NumberTypeSuffix: [ir] | 'ri'; - -fragment -ExponentPart -: - [eE] [+-]? Digits -; - -fragment -StringFragment: -'"' - ( - ESCAPED_QUOTE - | ~( '\n' | '\r' ) - )*? '"' - | '\'' - ( - ESCAPED_QUOTE - | ~( '\n' | '\r' ) - )*? '\'' - ; - -fragment -ShellCommandFrag: -'`' - ( - ESCAPED_QUOTE - | ~( '\n' | '\r' ) - )*? '`' -; - -fragment -IdentifierFrag:[a-zA-Z_] [a-zA-Z0-9_]* ; - -fragment -SingleCharacterString: - '?' ([a-zA-Z0-9_] | EscapedSequenceChar); - -/* -\nnn octal bit pattern, where nnn is 1-3 octal digits ([0-7]) -\xnn hexadecimal bit pattern, where nn is 1-2 hexadecimal digits ([0-9a-fA-F]) -\unnnn Unicode character, where nnnn is exactly 4 hexadecimal digits ([0-9a-fA-F]) -\u{nnnn ...} Unicode character(s), where each nnnn is 1-6 hexadecimal digits ([0-9a-fA-F]) -\cx or \C-x control character, where x is an ASCII printable character -\M-x meta character, where x is an ASCII printable character -\M-\C-x meta control character, where x is an ASCII printable character -\M-\cx same as above -\c\M-x same as above -\c? or \C-? delete, ASCII 7Fh (DEL) - */ -fragment -EscapedSequenceChar: - '\\' [abtnvfres] - | '\\' '\\' - | '\\' (HexDigit) (HexDigit) (HexDigit) - | '\\' [Xx] (HexDigit) (HexDigit) - | '\\' [uU] (HexDigit) (HexDigit) (HexDigit) (HexDigit) - | '\\' [uU] '{'((HexDigit) (HexDigit) (HexDigit) (HexDigit))+ '}' - | '\\' [Cc] '-'? PrintableCharacter - | '\\' [Mm] '-' PrintableCharacter - | '\\' [Mm] '-' '\\' [Cc] '-'? PrintableCharacter - | '\\' [Cc] '\\' [Mm] '-'? PrintableCharacter - | '\\' [Cc] '-'? '?' -; - -fragment -PrintableCharacter: [0-9A-Za-z] - |[!"#$%&'()*+,-./:;<=>?@[\]^_`~]; - - -mode HERE_DOC_MODE; -HereDocEnd1: IdentifierFrag - { - tryEndHereDoc(); - } - ; - -HereDocEnd2: StringFragment - { - tryEndHereDoc(); - } - ; - -AnyInHere: (.)+? - { - stringBuffer.append(getText()); - skip(); - } - ; -SL_COMMENT_IN_HEREDOC: ('#' ~( '\r' | '\n' )* '\r'? '\n') -> skip; - -ML_COMMENT_IN_HEREDOC: ('=begin' .*? '=end' '\r'? '\n') -> skip; - -mode QUOTED_STR_MODE; - -/* Make sure the percent string terminated at end of line */ -PercentStringLineEnd: [\r\n] - { - mode(DEFAULT_MODE); - setType(String); - setText(stringBuffer.toString()); - } - ; - -/* For any character which is alphabetic, add it into string */ -AnyInQuotedString1: ([A-Za-z0-9] |' ')+ - { - stringBuffer.append(getText()); - skip(); - } - ; -/* For string which forms a pair with start symbol, terminated the string - * Otherwise, add it into string - */ -AnyInQuotedString2: ~([A-Za-z0-9]|' ') - { - if (isQuotedPair(getText())){ - setType(String); - setText(stringBuffer.toString()); - mode(DEFAULT_MODE); - }else{ - stringBuffer.append(getText()); - skip(); - } - } -; - - diff --git a/src/main/antlr4/depends/extractor/ruby/RubyParser.g4 b/src/main/antlr4/depends/extractor/ruby/RubyParser.g4 deleted file mode 100644 index 17baa22..0000000 --- a/src/main/antlr4/depends/extractor/ruby/RubyParser.g4 +++ /dev/null @@ -1,300 +0,0 @@ -parser grammar RubyParser; - -options { tokenVocab= RubyLexer; } - -prog -: - statement_list_terms -; - -statement_list_terms -: - statement terms - | statement_list_terms statement terms - | terms -; - -statement_list_noterms -: - (statement terms)* statement -; - -statement -: - begin_block - | end_block - | alias_statement - | undef_statement - | require_statement - | ENSURE - | expr -; - -require_statement: REQUIRE String ; - -undef_statement: UNDEF function_name_or_symbol (',' function_name_or_symbol)*; - -alias_statement -: - ALIAS globalVar globalVar - | ALIAS function_name_or_symbol function_name_or_symbol -; - -function_name_or_symbol: - function_name - |symbol -; - - - - -begin_block -: - BEGIN_BLOCK LEFT_PAREN statement_list_terms RIGHT_PAREN -; - -end_block -: - END_BLOCK LEFT_PAREN statement_list_terms RIGHT_PAREN -; - -module_definition: - MODULE cpath statement_list_terms? END; - -class_definition: - class_header statement_list_terms? END -; -superclass: '<' id_symbol terms; - -class_header: - CLASS cpath superclass? - | CLASS BIT_SHL identifier -; - -function_definition -: - function_definition_header statement_list_terms? END -; - -function_definition_header -: - DEF function_name function_definition_params? expr? terms -; - -function_name -: cpath (QUESTION|SIGH|ASSIGN)? - | literal - | assignOperator - | mathOperator AT - | bitOperator - | compareOperator - | equalsOperator - | logicalOperator -; - -function_definition_params -: - LEFT_RBRACKET ( function_definition_param (',' crlfs? function_definition_param)*)? RIGHT_RBRACKET - | function_definition_param (',' crlfs? function_definition_param)* -; - -function_definition_param: - identifier - | MUL identifier - | MUL MUL identifier - | BIT_AND identifier - | hash_asso - | identifier ASSIGN expr -; - -function_call_param: - identifier - |hash_asso - |expr - | identifier ASSIGN expr -; - - -expr -: - primary - | expr ',' crlfs? expr - | expr dot_ref crlfs? expr - | expr postfix=QUESTION - | prefix=(PLUS| MINUS|MUL|MOD|BIT_AND) expr - | expr LEFT_SBRACKET expr RIGHT_SBRACKET /* array access */ - | prefix=DEFINED expr /* identifier definition test */ - | expr bop=(DOT2|DOT3) expr? /* range */ - | expr ','? MUL? ASSIGN crlfs? expr /* batch assign */ - | expr assignOperator crlfs? expr /* assign */ - | expr bop=PATTERN_MATCH expr /* pattern match */ - | expr bop=BIT_NOT expr /* pattern match */ - | expr SIGH BIT_NOT expr /* pattern match */ - | (not| BIT_NOT) expr /* logical not */ - | expr (compareOperator) crlfs? expr /* compare logical */ - | expr(logicalOperator) crlfs? expr /* logical join */ - | expr(equalsOperator) crlfs? expr /* equal test */ - | expr(mathOperator|bitOperator) crlfs? expr /* calcuation */ - | expr QUESTION expr COLON expr /* cond?true_part:false_part */ - | expr block - | expr expr_statement_suffix - | expr dot_ref CLASS - | function_name func_call_parameters_no_bracket expr_statement_suffix? - | expr dot_ref function_name func_call_parameters_no_bracket expr_statement_suffix? - | cpath (QUESTION|SIGH) - ; - -expr_statement_suffix: - IF crlfs? expr - | UNLESS crlfs? expr - | WHILE crlfs? expr - | UNTIL crlfs? expr - | RESCUE statement - | DO block_params? terms? statement_list_terms? END -; - -primary: - variable_path - | Regex - | symbol - | LEFT_RBRACKET expr RIGHT_RBRACKET /* (a) */ - | block - | BREAK expr? - | RETURN expr? - | RAISE expr - | RESCUE rescure_param? - | YIELD expr? - | BEGIN terms statement_list_terms? END - | IF crlfs? expr then_keyword statement_list_terms? if_tail* END - | WHEN expr then_keyword statement_list_noterms END - | UNLESS crlfs? expr then_keyword statement_list_terms? unless_tail? END - | CASE statement_list_terms? case_body* END - | CASE terms case_body* END - | WHILE crlfs? expr do_keyword statement_list_terms? END - | UNTIL crlfs? expr do_keyword statement_list_terms? END - | FOR crlfs? expr IN when_cond terms? statement_list_terms? END - | class_definition - | function_definition - | module_definition - | function_name func_call_parameters - | LEFT_PAREN crlfs? hash_asso crlfs?(',' crlfs? hash_asso)* ','? crlfs? RIGHT_PAREN /* hash */ - | LEFT_SBRACKET crlfs? expr crlfs? (',' crlfs? expr)* ','? crlfs? RIGHT_SBRACKET /* array */ - | LEFT_RBRACKET expr (DOT2|DOT3) expr? RIGHT_RBRACKET /* range */ - ; - - -func_call_parameters -: - LEFT_RBRACKET crlfs? function_call_param (',' crlfs? function_call_param)* crlfs? RIGHT_RBRACKET - | LEFT_RBRACKET crlfs? RIGHT_RBRACKET -; -func_call_parameters_no_bracket: - function_call_param (',' crlfs? function_call_param)* -; -rescure_param: id_symbol | hash_asso |ASSOC identifier; - -case_body: - WHEN when_cond (',' when_cond)* then_keyword statement_list_terms - |else_tail; - -when_cond: - expr - ; -unless_tail: - else_tail - ; - -if_tail: - ELSIF crlfs? expr terms statement_list_terms - | else_tail -; -else_tail: - ELSE crlfs? statement_list_terms; - - -dot_ref: DOT | ANDDOT ; - - -logicalOperator: OR| AND; - -equalsOperator: EQUAL| NOT_EQUAL | EQUAL3; - -compareOperator: LESS|GREATER|LESS_EQUAL| GREATER_EQUAL; - -bitOperator: BIT_SHL|BIT_SHR|BIT_AND|BIT_OR|BIT_XOR; - -mathOperator: MUL|DIV|MOD|PLUS|MINUS|EXP; - -assignOperator: - PLUS_ASSIGN | MINUS_ASSIGN |MUL_ASSIGN|DIV_ASSIGN|MOD_ASSIGN - | EXP_ASSIGN |BIT_OR_ASSIGN|BIT_AND_ASSIGN|OR_ASSIGN|AND_ASSIGN - | BIT_XOR_ASSIGN | BIT_NOT_ASSIGN |BIT_SHL_ASSIGN | BIT_SHR_ASSIGN; - -not: NOT | SIGH; - -block: LEFT_PAREN crlfs? block_params? statement_list_noterms crlfs? (',' statement_list_noterms crlfs?)* RIGHT_PAREN; - -block_params: BIT_OR expr (',' expr)* BIT_OR; - -id_symbol: - cpath - | COLON cpath - ; - -symbol: - COLON identifier - COLON string - | COLON function_name -; - -hash_asso: - expr ASSOC expr - | expr COLON expr -; - -variable_path: - identifier - |literal - | variable_path COLON2 variable_path - | COLON2 variable_path - ; -cpath: - identifier ((COLON2|DOT) identifier)* - ; -literal: - Float - | string - | Integer - |(TRUE| FALSE) - | NIL - | Float DOT -; - - -identifier: Identifier | globalVar | classVar |instanceVar | idArg | NEXT |REDO |RETRY | BREAK |SELF | SUPER |NIL |REQUIRE | empty; - -empty: - LEFT_PAREN RIGHT_PAREN /* empty block */ - | LEFT_SBRACKET RIGHT_SBRACKET /* empty array */ - ; - -globalVar: DOLLAR Identifier; -classVar: AT AT Identifier; -instanceVar: AT Identifier; -idArg: DOLLAR Integer | DollarSpecial; - -do_keyword: (DO|COLON) terms | terms ; -then_keyword: (THEN|COLON) terms? | terms; -string: String+; /* many string can be concatenated */ - -crlfs: (SL_COMMENT|CRLF)+; - -terms: - (term)+ -; - -term: SEMICOLON | CRLF | SL_COMMENT; - - - - diff --git a/src/main/antlr4/depends/extractor/ruby/compiletest.sh b/src/main/antlr4/depends/extractor/ruby/compiletest.sh deleted file mode 100755 index fe44907..0000000 --- a/src/main/antlr4/depends/extractor/ruby/compiletest.sh +++ /dev/null @@ -1,11 +0,0 @@ -rm *.java -rm *.class - -export CLASSPATH=.:/usr/share/java/stringtemplate4.jar:/usr/share/java/antlr4.jar:/usr/share/java/antlr4-runtime.jar:/usr/share/java/antlr3-runtime.jar/:/usr/share/java/treelayout.jar - -antlr4 RubyLexer.g4 -antlr4 RubyParser.g4 - -javac -cp $CLASSPATH *.java - -exec java -cp $CLASSPATH org.antlr.v4.gui.TestRig Ruby prog $1 diff --git a/src/main/antlr4/depends/extractor/ruby/debug.sh b/src/main/antlr4/depends/extractor/ruby/debug.sh deleted file mode 100755 index e4dd35c..0000000 --- a/src/main/antlr4/depends/extractor/ruby/debug.sh +++ /dev/null @@ -1,3 +0,0 @@ -export CLASSPATH=.:/usr/share/java/stringtemplate4.jar:/usr/share/java/antlr4.jar:/usr/share/java/antlr4-runtime.jar:/usr/share/java/antlr3-runtime.jar/:/usr/share/java/treelayout.jar - -exec java -cp $CLASSPATH org.antlr.v4.gui.TestRig Ruby prog $1 -SLL -tokens -trace -disgnostics diff --git a/src/main/antlr4/depends/extractor/ruby/test.sh b/src/main/antlr4/depends/extractor/ruby/test.sh deleted file mode 100755 index 2362628..0000000 --- a/src/main/antlr4/depends/extractor/ruby/test.sh +++ /dev/null @@ -1,3 +0,0 @@ -export CLASSPATH=.:/usr/share/java/stringtemplate4.jar:/usr/share/java/antlr4.jar:/usr/share/java/antlr4-runtime.jar:/usr/share/java/antlr3-runtime.jar/:/usr/share/java/treelayout.jar - -exec java -cp $CLASSPATH org.antlr.v4.gui.TestRig Ruby prog $1 diff --git a/src/main/antlr4/depends/extractor/ruby/test/BEGIN_END.rb b/src/main/antlr4/depends/extractor/ruby/test/BEGIN_END.rb deleted file mode 100644 index 0b19563..0000000 --- a/src/main/antlr4/depends/extractor/ruby/test/BEGIN_END.rb +++ /dev/null @@ -1,12 +0,0 @@ -#!/usr/bin/ruby - -puts "Hello World!"; - -BEGIN { - puts "初始化 Ruby 程序" -} - -END { - puts "停止 Ruby 程序" -} - diff --git a/src/main/antlr4/depends/extractor/ruby/test/ambgious1.rb b/src/main/antlr4/depends/extractor/ruby/test/ambgious1.rb deleted file mode 100644 index dccb962..0000000 --- a/src/main/antlr4/depends/extractor/ruby/test/ambgious1.rb +++ /dev/null @@ -1,4 +0,0 @@ -3 + 2 -3+2 -3 +2 -3+ 2 diff --git a/src/main/antlr4/depends/extractor/ruby/test/ambgious2.rb b/src/main/antlr4/depends/extractor/ruby/test/ambgious2.rb deleted file mode 100644 index ff419ab..0000000 --- a/src/main/antlr4/depends/extractor/ruby/test/ambgious2.rb +++ /dev/null @@ -1,4 +0,0 @@ -f[0] -f [0] -f([0]) -f ([0]) diff --git a/src/main/antlr4/depends/extractor/ruby/test/array_ref.rb b/src/main/antlr4/depends/extractor/ruby/test/array_ref.rb deleted file mode 100644 index eeec89f..0000000 --- a/src/main/antlr4/depends/extractor/ruby/test/array_ref.rb +++ /dev/null @@ -1,2 +0,0 @@ - read.unpack('N')[0] - diff --git a/src/main/antlr4/depends/extractor/ruby/test/assign.rb b/src/main/antlr4/depends/extractor/ruby/test/assign.rb deleted file mode 100644 index 6cf6263..0000000 --- a/src/main/antlr4/depends/extractor/ruby/test/assign.rb +++ /dev/null @@ -1 +0,0 @@ - writer, * = write_datum(datum_to_write, writers_schema) diff --git a/src/main/antlr4/depends/extractor/ruby/test/assign1.rb b/src/main/antlr4/depends/extractor/ruby/test/assign1.rb deleted file mode 100644 index e6e301c..0000000 --- a/src/main/antlr4/depends/extractor/ruby/test/assign1.rb +++ /dev/null @@ -1 +0,0 @@ -x, (y, z) = 1, 2, 3 diff --git a/src/main/antlr4/depends/extractor/ruby/test/attr_accessor.rb b/src/main/antlr4/depends/extractor/ruby/test/attr_accessor.rb deleted file mode 100644 index b895828..0000000 --- a/src/main/antlr4/depends/extractor/ruby/test/attr_accessor.rb +++ /dev/null @@ -1,9 +0,0 @@ - class SummaryReporter < StatisticsReporter - attr_accessor :sync - attr_accessor :old_sync - - def statistics # :nodoc: - "Finished in %.6fs, %.4f runs/s, %.4f assertions/s." % - [total_time, count / total_time, assertions / total_time] - end -end diff --git a/src/main/antlr4/depends/extractor/ruby/test/block.rb b/src/main/antlr4/depends/extractor/ruby/test/block.rb deleted file mode 100644 index e7d9752..0000000 --- a/src/main/antlr4/depends/extractor/ruby/test/block.rb +++ /dev/null @@ -1,13 +0,0 @@ - if messages - hsh['messages'] = messages.inject ({}){ |h, (k,t)| h[k] = t.to_avro(names);h } - end - - - def validate_possible_types(datum, expected_schema, path) - expected_schema.schemas.map do |schema| - result = Result.new - validate_recursive(schema, datum, path, result) - { type, t} - end - end - diff --git a/src/main/antlr4/depends/extractor/ruby/test/case.rb b/src/main/antlr4/depends/extractor/ruby/test/case.rb deleted file mode 100644 index 82f00f7..0000000 --- a/src/main/antlr4/depends/extractor/ruby/test/case.rb +++ /dev/null @@ -1,2 +0,0 @@ - @tty = STDERR.tty? && !STDOUT.tty? && !~ ENV["TERM"] if @tty.nil? - @eol = @tty && !@verbose ? "\r\e[K\r" : "\n" diff --git a/src/main/antlr4/depends/extractor/ruby/test/class.rb b/src/main/antlr4/depends/extractor/ruby/test/class.rb deleted file mode 100644 index 524296a..0000000 --- a/src/main/antlr4/depends/extractor/ruby/test/class.rb +++ /dev/null @@ -1,34 +0,0 @@ -class Customer -end - -class CustomerWithFieldAndMethod - @@no_of_customers=0 - def hello - puts "Hello Ruby!" - end -end - - -def newObject - cust1 = Customer. new - cust2 = Customer. new -end - -class CustomerWithNewParameters - @@no_of_customers=0 - def initialize(id, name, addr) - @cust_id=id - @cust_name=name - @cust_addr=addr - end - def display_details() - puts "Customer id #@cust_id" - puts "Customer name #@cust_name" - puts "Customer address #@cust_addr" - end -end - -cust1=CustomerWithNewParameters.new("1", "John", "Wisdom Apartments, Ludhiya") - - -cust1.display_details() diff --git a/src/main/antlr4/depends/extractor/ruby/test/class2.rb b/src/main/antlr4/depends/extractor/ruby/test/class2.rb deleted file mode 100644 index 402ccde..0000000 --- a/src/main/antlr4/depends/extractor/ruby/test/class2.rb +++ /dev/null @@ -1,4 +0,0 @@ - class << self - puts aa; - end - diff --git a/src/main/antlr4/depends/extractor/ruby/test/comment-in-block.rb b/src/main/antlr4/depends/extractor/ruby/test/comment-in-block.rb deleted file mode 100644 index cca567c..0000000 --- a/src/main/antlr4/depends/extractor/ruby/test/comment-in-block.rb +++ /dev/null @@ -1,9 +0,0 @@ -puts "hello" -=begin -这是注释。 -这也是注释。 -这也是注释。 -这还是注释。 -=end -puts "hello" - diff --git a/src/main/antlr4/depends/extractor/ruby/test/comment-singleline-with-additional-terms.rb b/src/main/antlr4/depends/extractor/ruby/test/comment-singleline-with-additional-terms.rb deleted file mode 100644 index 1d34f63..0000000 --- a/src/main/antlr4/depends/extractor/ruby/test/comment-singleline-with-additional-terms.rb +++ /dev/null @@ -1,11 +0,0 @@ -# this is a comments - -# this is another comment - -; - -; - - - - diff --git a/src/main/antlr4/depends/extractor/ruby/test/comment-singleline.rb b/src/main/antlr4/depends/extractor/ruby/test/comment-singleline.rb deleted file mode 100644 index 0c71baa..0000000 --- a/src/main/antlr4/depends/extractor/ruby/test/comment-singleline.rb +++ /dev/null @@ -1,3 +0,0 @@ -# this is a comments - -# this is another comment diff --git a/src/main/antlr4/depends/extractor/ruby/test/comment_in_middle.rb b/src/main/antlr4/depends/extractor/ruby/test/comment_in_middle.rb deleted file mode 100644 index 8e1d5a9..0000000 --- a/src/main/antlr4/depends/extractor/ruby/test/comment_in_middle.rb +++ /dev/null @@ -1,3 +0,0 @@ -#!/usr/bin/ruby - -puts "Hello World!"; # this is a trailing comment diff --git a/src/main/antlr4/depends/extractor/ruby/test/dis_regex.rb b/src/main/antlr4/depends/extractor/ruby/test/dis_regex.rb deleted file mode 100644 index 908ac9d..0000000 --- a/src/main/antlr4/depends/extractor/ruby/test/dis_regex.rb +++ /dev/null @@ -1 +0,0 @@ -[total_time, count / total_time, assertions / total_time] diff --git a/src/main/antlr4/depends/extractor/ruby/test/dotref.rb b/src/main/antlr4/depends/extractor/ruby/test/dotref.rb deleted file mode 100644 index 76b5354..0000000 --- a/src/main/antlr4/depends/extractor/ruby/test/dotref.rb +++ /dev/null @@ -1 +0,0 @@ - ((orig_args).map).join abc diff --git a/src/main/antlr4/depends/extractor/ruby/test/expression.rb b/src/main/antlr4/depends/extractor/ruby/test/expression.rb deleted file mode 100644 index 2ffd926..0000000 --- a/src/main/antlr4/depends/extractor/ruby/test/expression.rb +++ /dev/null @@ -1,28 +0,0 @@ -a=1; -a=1.0; -a="1"; -a=true; -a=false; -a=true|false; -a=true||false; -a=nil; -a=(a+b); -a=-a; -a=+a; -a=!a; -a=~a; -a=a=b; -a=(a>=b)&&(a<=b)&&(a>b)||(a>b); -a=(a==b)&&(a!=b); -a=defined? a; -a=a.m; -a=a::m; -a=a&.m; -a=(a..b); -a={a=>1,b=>2,c=>3}; -a={a=>1,b=>1,c=>1,}; -a=[a,b,c]; -a=[a,b,c,]; - diff --git a/src/main/antlr4/depends/extractor/ruby/test/func.rb b/src/main/antlr4/depends/extractor/ruby/test/func.rb deleted file mode 100644 index c78889c..0000000 --- a/src/main/antlr4/depends/extractor/ruby/test/func.rb +++ /dev/null @@ -1,43 +0,0 @@ -#!/usr/bin/ruby -# -*- coding: UTF-8 -*- - - def to_s; writer.string; end - -def test(a1="Ruby", a2="Perl") - puts "编程语言为 #{a1}" - puts "编程语言为 #{a2}" -end - -def test1(a1, a2) - puts "编程语言为 #{a1}" - puts "编程语言为 #{a2}" -end -test "C", "C++" -def test - i = 100 - j = 200 - k = 300 - return i,j,k -end -var = test -puts var - -def sample (*test) - puts "参数个数为 #{test.length}" - for i in 0...test.length - puts "参数值为 #{test[i]}" - end -end -sample "Zara", "6", "F" -sample "Mac", "36", "M", "MCA" - - def remote_protocol=(new_remote_protocol) - @remote_protocol = new_remote_protocol - REMOTE_PROTOCOLS[transport.remote_name] = remote_protocol - end - - def remote_hash=(new_remote_hash) - @remote_hash = new_remote_hash - REMOTE_HASHES[transport.remote_name] = remote_hash - end - diff --git a/src/main/antlr4/depends/extractor/ruby/test/func1.rb b/src/main/antlr4/depends/extractor/ruby/test/func1.rb deleted file mode 100644 index eae9f99..0000000 --- a/src/main/antlr4/depends/extractor/ruby/test/func1.rb +++ /dev/null @@ -1,18 +0,0 @@ - def write_handshake_request(encoder) - local_hash = local_protocol.md5 - remote_name = transport.remote_name - remote_hash = REMOTE_HASHES[remote_name] - unless remote_hash - remote_hash = local_hash - self.remote_protocol = local_protocol - end - request_datum = { - 'clientHash' => local_hash, - 'serverHash' => remote_hash - } - if send_protocol - request_datum['clientProtocol'] = local_protocol.to_s - end - HANDSHAKE_REQUESTOR_WRITER.write(request_datum, encoder) - end - diff --git a/src/main/antlr4/depends/extractor/ruby/test/func2.rb b/src/main/antlr4/depends/extractor/ruby/test/func2.rb deleted file mode 100644 index b10359a..0000000 --- a/src/main/antlr4/depends/extractor/ruby/test/func2.rb +++ /dev/null @@ -1 +0,0 @@ - hash_to_schema(fields: [{ type: 'null', name: 'sub' }]) diff --git a/src/main/antlr4/depends/extractor/ruby/test/func3.rb b/src/main/antlr4/depends/extractor/ruby/test/func3.rb deleted file mode 100755 index 33b2622..0000000 --- a/src/main/antlr4/depends/extractor/ruby/test/func3.rb +++ /dev/null @@ -1,12 +0,0 @@ -class Reader - include ::Enumerable - - # The reader and binary decoder for the raw file stream - attr_reader :reader, :decoder - - # The binary decoder for the contents of a block (after codec decompression) - attr_reader :block_decoder - - attr_reader :datum_reader, :sync_marker, :meta, :file_length, :codec - attr_accessor :block_count # records remaining in current block -end diff --git a/src/main/antlr4/depends/extractor/ruby/test/func_call.rb b/src/main/antlr4/depends/extractor/ruby/test/func_call.rb deleted file mode 100644 index fe821e3..0000000 --- a/src/main/antlr4/depends/extractor/ruby/test/func_call.rb +++ /dev/null @@ -1,10 +0,0 @@ -if w_type == r_type - return true if Schema::PRIMITIVE_TYPES_SYM.include(r_type) -end - - def test_parse - EXAMPLES.each do |example| - assert_nothing_raised("should be valid: #{example.protocol_string}") - end - end - diff --git a/src/main/antlr4/depends/extractor/ruby/test/func_call2.rb b/src/main/antlr4/depends/extractor/ruby/test/func_call2.rb deleted file mode 100644 index 5481f2c..0000000 --- a/src/main/antlr4/depends/extractor/ruby/test/func_call2.rb +++ /dev/null @@ -1 +0,0 @@ - MAGIC = "Obj" + [VERSION].pack('c') diff --git a/src/main/antlr4/depends/extractor/ruby/test/func_param.rb b/src/main/antlr4/depends/extractor/ruby/test/func_param.rb deleted file mode 100644 index 24b2fe7..0000000 --- a/src/main/antlr4/depends/extractor/ruby/test/func_param.rb +++ /dev/null @@ -1,3 +0,0 @@ - def rubinius? platform = defined?(RUBY_ENGINE) && RUBY_ENGINE - "rbx" == platform - end diff --git a/src/main/antlr4/depends/extractor/ruby/test/function_name.rb b/src/main/antlr4/depends/extractor/ruby/test/function_name.rb deleted file mode 100644 index 281de78..0000000 --- a/src/main/antlr4/depends/extractor/ruby/test/function_name.rb +++ /dev/null @@ -1,7 +0,0 @@ -if $0 == __FILE__ - server = WEBrick::HTTPServer.new(:Port) - server.mount '/', MailHandler - trap("INT") { server.shutdown } - server.start -end - diff --git a/src/main/antlr4/depends/extractor/ruby/test/global_varref.rb b/src/main/antlr4/depends/extractor/ruby/test/global_varref.rb deleted file mode 100644 index b7b8216..0000000 --- a/src/main/antlr4/depends/extractor/ruby/test/global_varref.rb +++ /dev/null @@ -1 +0,0 @@ - on_signal ::Minitest.info_signal, handler, &block diff --git a/src/main/antlr4/depends/extractor/ruby/test/hash.rb b/src/main/antlr4/depends/extractor/ruby/test/hash.rb deleted file mode 100644 index c233d57..0000000 --- a/src/main/antlr4/depends/extractor/ruby/test/hash.rb +++ /dev/null @@ -1,22 +0,0 @@ -field_schema_hash = { 'type' => 'record', 'name' => 'Record', 'namespace' => 'my.name.space', 'fields' => [ { 'name' => 'name', 'type' => 'boolean', 'doc' => 'documentation' } ] } - - -field_schema_hash = { - 'type' => 'record', - 'name' => 'Record', - 'namespace' => 'my.name.space' - } - -field_schema_hash = - { - 'type' => 'record', - 'name' => 'Record', - 'namespace' => 'my.name.space', - 'fields' => [ - { - 'name' => 'name', - 'type' => 'boolean', - 'doc' => 'documentation' - } - ] - } diff --git a/src/main/antlr4/depends/extractor/ruby/test/helloworld.rb b/src/main/antlr4/depends/extractor/ruby/test/helloworld.rb deleted file mode 100644 index 3820462..0000000 --- a/src/main/antlr4/depends/extractor/ruby/test/helloworld.rb +++ /dev/null @@ -1,3 +0,0 @@ -#!/usr/bin/ruby - -puts "Hello World!"; diff --git a/src/main/antlr4/depends/extractor/ruby/test/heredoc.rb b/src/main/antlr4/depends/extractor/ruby/test/heredoc.rb deleted file mode 100644 index 0f520aa..0000000 --- a/src/main/antlr4/depends/extractor/ruby/test/heredoc.rb +++ /dev/null @@ -1,16 +0,0 @@ -#!/usr/bin/ruby -print <<-EOF - This is the first way of creating - here document ie. multiple line string. -EOF - -print <<-"EOF"; # 与上面相同 - This is the second way of creating - here document ie. multiple line string. -EOF - -print <<`EOC` # 执行命令 - echo hi there - echo lo there -EOC - diff --git a/src/main/antlr4/depends/extractor/ruby/test/heredoc1.rb b/src/main/antlr4/depends/extractor/ruby/test/heredoc1.rb deleted file mode 100644 index 61cfe98..0000000 --- a/src/main/antlr4/depends/extractor/ruby/test/heredoc1.rb +++ /dev/null @@ -1,24 +0,0 @@ -#!/usr/bin/ruby -puts 123 -print <<-EOK - 123 "aaa" - 123 "aaa" -EOK - -print <<-EOK - 123 "aaa" - 123 "aaa" -EOK - -print <<-"abc123\n" - 123 "aaa" - 123 "aaa" -"abc123\n" - -print <<-"abc" - 123 "aaa" - 123 "aaa" -abc - - - diff --git a/src/main/antlr4/depends/extractor/ruby/test/heredoc2.rb b/src/main/antlr4/depends/extractor/ruby/test/heredoc2.rb deleted file mode 100644 index 55a09bc..0000000 --- a/src/main/antlr4/depends/extractor/ruby/test/heredoc2.rb +++ /dev/null @@ -1,8 +0,0 @@ - schema = Avro::Schema.parse(<<-JSON) - { "type": "#{type}" } - JSON - -expected_type = <<-JSON.strip - {"name":"cards.suit","type":"enum","symbols":["club","hearts","diamond","spades"]} - JSON - diff --git a/src/main/antlr4/depends/extractor/ruby/test/infinite_loop_err.rb b/src/main/antlr4/depends/extractor/ruby/test/infinite_loop_err.rb deleted file mode 100644 index feaea30..0000000 --- a/src/main/antlr4/depends/extractor/ruby/test/infinite_loop_err.rb +++ /dev/null @@ -1,14 +0,0 @@ -@pieces = [ - Piece.new( [ :nw, :ne, :east, :east ], 2), - Piece.new( [ :ne, :se, :east, :ne ], 7), - Piece.new( [ :east, :sw, :sw, :se ], 6), - Piece.new( [ :se, :se, :east, :se ], 8), - Piece.new( [ :se, :se, :east, :se ], 8), - Piece.new( [ :nw, :ne, :east, :east ], 2), - Piece.new( [ :ne, :se, :east, :ne ], 7), - Piece.new( [ :east, :sw, :sw, :se ], 6), - Piece.new( [ :se, :se, :east, :se ], 8), - Piece.new( [ :se, :se, :east, :se ], 8), - Piece.new( [ :east, :east, :sw, :se ], 3) - ]; - diff --git a/src/main/antlr4/depends/extractor/ruby/test/literals.rb b/src/main/antlr4/depends/extractor/ruby/test/literals.rb deleted file mode 100644 index 15b48f4..0000000 --- a/src/main/antlr4/depends/extractor/ruby/test/literals.rb +++ /dev/null @@ -1,51 +0,0 @@ -#!/usr/bin/ruby - -puts "Hello World!"; - -puts 1; - -puts 1+1-1*1/1**1; - -puts 1.0-1.2 - -puts 123; # Fixnum 十进制 -puts 1_123; # Fixnum 十进制 -puts -500; # 负的 Fixnum -puts 0377;# 八进制 -puts 12345678901234567890; # 大数 -puts 0xff; #十六进制 -puts 0.211; #小数 -puts -0.211; #小数 -puts 0b1011; # 二进制 -puts "a".ord; # "a" 的字符编码 -puts ?\n; # 换行符(0x0a)的编码 -puts 'h' - - -puts 123.4; # -puts 1.0e6; #科学记数法 -puts 4E20; #不是必需的 -puts 4e+20; #指数前的符号 - -#浮点型 -puts 0.0 -puts 2.1 -#puts 1000000. - -#string literals -puts 'escape using "\\"'; -puts 'That\'s right'; - -"相乘 : #{24*60*60}"; - -desc1 = %Q{Ruby 的字符串可以使用 '' 和 ""。} -desc2 = %q|Ruby 的字符串可以使用 '' 和 ""。| - -# hash -colors = { "red" => 0xf00, "green" => 0x0f0, "blue" => 0x00f } - -# array -array=["fred", 10, 3.14, "This is a string", "last element",] - -#range -puts (a..b) diff --git a/src/main/antlr4/depends/extractor/ruby/test/loop.rb b/src/main/antlr4/depends/extractor/ruby/test/loop.rb deleted file mode 100644 index a54f96f..0000000 --- a/src/main/antlr4/depends/extractor/ruby/test/loop.rb +++ /dev/null @@ -1,2 +0,0 @@ -*a = loop do break; end; test_ok(a == [nil]) - diff --git a/src/main/antlr4/depends/extractor/ruby/test/loop_statement.rb b/src/main/antlr4/depends/extractor/ruby/test/loop_statement.rb deleted file mode 100644 index 26d5eb6..0000000 --- a/src/main/antlr4/depends/extractor/ruby/test/loop_statement.rb +++ /dev/null @@ -1,53 +0,0 @@ -#!/usr/bin/ruby -# -*- coding: UTF-8 -*- - -$i = 0 -$num = 5 - -while $i < $num do - puts("在循环语句中 i = #$i" ) - $i +=1 -end - - -#!/usr/bin/ruby -# -*- coding: UTF-8 -*- - -$i = 0 -$num = 5 -begin - puts("在循环语句中 i = #$i" ) - $i +=1 -end while $i < $num - -puts("在循环语句中 i = #$i" ) while $i < $num - - -#!/usr/bin/ruby -# -*- coding: UTF-8 -*- - -$i = 0 -$num = 5 - -until $i > $num do - puts("在循环语句中 i = #$i" ) - break - break - redo - next - $i +=1; -end - -puts("在循环语句中 i = #$i" ) until $i < $num - -#!/usr/bin/ruby -# -*- coding: UTF-8 -*- - -for i in 0..5 - puts "局部变量的值为 #{i}" -end - -(0..5).each do |i| - puts "局部变量的值为 #{i}" -end - diff --git a/src/main/antlr4/depends/extractor/ruby/test/minitest.rb b/src/main/antlr4/depends/extractor/ruby/test/minitest.rb deleted file mode 100644 index 8f0541a..0000000 --- a/src/main/antlr4/depends/extractor/ruby/test/minitest.rb +++ /dev/null @@ -1,857 +0,0 @@ -require "optparse" -require "thread" -require "mutex_m" -require "minitest/parallel" -require "stringio" - -## -# :include: README.rdoc - -module Minitest - VERSION = "5.10.3" # :nodoc: - ENCS = "".respond_to? :encoding # :nodoc: - - @@installed_at_exit ||= false - @@after_run = [] - @extensions = [] - - mc = (class << self; self; end) - - ## - # Parallel test executor - - mc.send :attr_accessor, :parallel_executor - self.parallel_executor = Parallel::Executor.new((ENV["N"] || 2).to_i) - - ## - # Filter object for backtraces. - - mc.send :attr_accessor, :backtrace_filter - - ## - # Reporter object to be used for all runs. - # - # NOTE: This accessor is only available during setup, not during runs. - - mc.send :attr_accessor, :reporter - - ## - # Names of known extension plugins. - - mc.send :attr_accessor, :extensions - - ## - # The signal to use for dumping information to STDERR. Defaults to "INFO". - - mc.send :attr_accessor, :info_signal - self.info_signal = "INFO" - - ## - # Registers Minitest to run at process exit - - def self.autorun - at_exit { - next if $! and not ($!.kind_of? SystemExit and $!.success?) - - exit_code = nil - - at_exit { - @@after_run.reverse_each(&:call) - exit exit_code || false - } - - exit_code = Minitest.run ARGV - } unless @@installed_at_exit - @@installed_at_exit = true - end - - ## - # A simple hook allowing you to run a block of code after everything - # is done running. Eg: - # - # Minitest.after_run { p $debugging_info } - - def self.after_run &block - @@after_run << block - end - - def self.init_plugins options # :nodoc: - self.extensions.each do |name| - msg = "plugin_#{name}_init" - send msg, options if self.respond_to? msg - end - end - - def self.load_plugins # :nodoc: - return unless self.extensions.empty? - - seen = {} - - #require "rubygems" unless defined? Gem - - Gem.find_files("minitest/*_plugin.rb").each do |plugin_path| - name = File.basename plugin_path, "_plugin.rb" - - next if seen[name] - seen[name] = true - - require plugin_path - self.extensions << name - end - end - - ## - # This is the top-level run method. Everything starts from here. It - # tells each Runnable sub-class to run, and each of those are - # responsible for doing whatever they do. - # - # The overall structure of a run looks like this: - # - # Minitest.autorun - # Minitest.run(args) - # Minitest.__run(reporter, options) - # Runnable.runnables.each - # runnable.run(reporter, options) - # self.runnable_methods.each - # self.run_one_method(self, runnable_method, reporter) - # Minitest.run_one_method(klass, runnable_method) - # klass.new(runnable_method).run - - def self.run args = [] - self.load_plugins - - options = process_args args - - reporter = CompositeReporter.new - reporter << SummaryReporter.new(options[:io], options) - reporter << ProgressReporter.new(options[:io], options) - - self.reporter = reporter # this makes it available to plugins - self.init_plugins options - self.reporter = nil # runnables shouldn't depend on the reporter, ever - - self.parallel_executor.start if parallel_executor.respond_to?(:start) - reporter.start - begin - __run reporter, options - rescue Interrupt - warn "Interrupted. Exiting..." - end - self.parallel_executor.shutdown - reporter.report - - reporter.passed? - end - - ## - # Internal run method. Responsible for telling all Runnable - # sub-classes to run. - - def self.__run reporter, options - suites = Runnable.runnables.reject { |s| s.runnable_methods.empty? }.shuffle - parallel, serial = suites.partition { |s| s.test_order == :parallel } - - # If we run the parallel tests before the serial tests, the parallel tests - # could run in parallel with the serial tests. This would be bad because - # the serial tests won't lock around Reporter#record. Run the serial tests - # first, so that after they complete, the parallel tests will lock when - # recording results. - serial.map { |suite| suite.run reporter, options } + - parallel.map { |suite| suite.run reporter, options } - end - - def self.process_args args = [] # :nodoc: - options = { - :io => $stdout, - } - orig_args = args.dup - - OptionParser.new do |opts| - opts.banner = "minitest options:" - opts.version = Minitest::VERSION - - opts.on "-h", "--help", "Display this help." do - puts opts - exit - end - - desc = "Sets random seed. Also via env. Eg: SEED=n rake" - opts.on "-s", "--seed SEED", Integer, desc do |m| - options[:seed] = m.to_i - end - - opts.on "-v", "--verbose", "Verbose. Show progress processing files." do - options[:verbose] = true - end - - opts.on "-n", "--name PATTERN", "Filter run on /regexp/ or string." do |a| - options[:filter] = a - end - - opts.on "-e", "--exclude PATTERN", "Exclude /regexp/ or string from run." do |a| - options[:exclude] = a - end - - unless extensions.empty? - opts.separator "" - opts.separator "Known extensions: #{extensions.join(", ")}" - - extensions.each do |meth| - msg = "plugin_#{meth}_options" - send msg, opts, options if self.respond_to?(msg) - end - end - - begin - opts.parse! args - rescue OptionParser::InvalidOption => e - puts - puts e - puts - puts opts - exit 1 - end - - orig_args -= args - end - - unless options[:seed] then - srand - options[:seed] = (ENV["SEED"] || srand).to_i % 0xFFFF - orig_args << "--seed" << options[:seed].to_s - end - - srand options[:seed] - - options[:args] = orig_args.map { |s| - s =~ /[\s|&<>$()]/ ? s.inspect : s - }.join " " - - options - end - - def self.filter_backtrace bt # :nodoc: - backtrace_filter.filter bt - end - - ## - # Represents anything "runnable", like Test, Spec, Benchmark, or - # whatever you can dream up. - # - # Subclasses of this are automatically registered and available in - # Runnable.runnables. - - class Runnable - ## - # Number of assertions executed in this run. - - attr_accessor :assertions - - ## - # An assertion raised during the run, if any. - - attr_accessor :failures - - ## - # Name of the run. - - def name - @NAME - end - - ## - # Set the name of the run. - - def name= o - @NAME = o - end - - def self.inherited klass # :nodoc: - self.runnables << klass - super - end - - ## - # Returns all instance methods matching the pattern +re+. - - def self.methods_matching re - public_instance_methods(true).grep(re).map(&:to_s) - end - - def self.reset # :nodoc: - @@runnables = [] - end - - reset - - ## - # Responsible for running all runnable methods in a given class, - # each in its own instance. Each instance is passed to the - # reporter to record. - - def self.run reporter, options = {} - filter = options[:filter] || "/./" - filter = Regexp.new $1 if filter =~ %r%/(.*)/% - - filtered_methods = self.runnable_methods.find_all { |m| - filter === m || filter === "#{self}##{m}" - } - - exclude = options[:exclude] - exclude = Regexp.new $1 if exclude =~ %r%/(.*)/% - - filtered_methods.delete_if { |m| - exclude === m || exclude === "#{self}##{m}" - } - - return if filtered_methods.empty? - - with_info_handler reporter do - filtered_methods.each do |method_name| - run_one_method self, method_name, reporter - end - end - end - - ## - # Runs a single method and has the reporter record the result. - # This was considered internal API but is factored out of run so - # that subclasses can specialize the running of an individual - # test. See Minitest::ParallelTest::ClassMethods for an example. - - def self.run_one_method klass, method_name, reporter - reporter.prerecord klass, method_name - reporter.record Minitest.run_one_method(klass, method_name) - end - - def self.with_info_handler reporter, &block # :nodoc: - handler = lambda do - unless reporter.passed? then - warn "Current results:" - warn "" - warn reporter.reporters.first - warn "" - end - end - - on_signal ::Minitest.info_signal, handler, &block - end - - SIGNALS = Signal.list # :nodoc: - - def self.on_signal name, action # :nodoc: - supported = SIGNALS[name] - - old_trap = trap name do - old_trap.call if old_trap.respond_to? :call - action.call - end if supported - - yield - ensure - trap name, old_trap if supported - end - - ## - # Each subclass of Runnable is responsible for overriding this - # method to return all runnable methods. See #methods_matching. - - def self.runnable_methods - raise NotImplementedError, "subclass responsibility" - end - - ## - # Returns all subclasses of Runnable. - - def self.runnables - @@runnables - end - - def marshal_dump # :nodoc: - [self.name, self.failures, self.assertions] - end - - def marshal_load ary # :nodoc: - self.name, self.failures, self.assertions = ary - end - - def failure # :nodoc: - self.failures.first - end - - def initialize name # :nodoc: - self.name = name - self.failures = [] - self.assertions = 0 - end - - ## - # Runs a single method. Needs to return self. - - def run - raise NotImplementedError, "subclass responsibility" - end - - ## - # Did this run pass? - # - # Note: skipped runs are not considered passing, but they don't - # cause the process to exit non-zero. - - def passed? - raise NotImplementedError, "subclass responsibility" - end - - ## - # Returns a single character string to print based on the result - # of the run. Eg ".", "F", or "E". - - def result_code - raise NotImplementedError, "subclass responsibility" - end - - ## - # Was this run skipped? See #passed? for more information. - - def skipped? - raise NotImplementedError, "subclass responsibility" - end - end - - ## - # Defines the API for Reporters. Subclass this and override whatever - # you want. Go nuts. - - class AbstractReporter - include Mutex_m - - ## - # Starts reporting on the run. - - def start - end - - ## - # About to start running a test. This allows a reporter to show - # that it is starting or that we are in the middle of a test run. - - def prerecord klass, name - end - - ## - # Record a result and output the Runnable#result_code. Stores the - # result of the run if the run did not pass. - - def record result - end - - ## - # Outputs the summary of the run. - - def report - end - - ## - # Did this run pass? - - def passed? - true - end - end - - class Reporter < AbstractReporter # :nodoc: - ## - # The IO used to report. - - attr_accessor :io - - ## - # Command-line options for this run. - - attr_accessor :options - - def initialize io = $stdout, options = {} # :nodoc: - super() - self.io = io - self.options = options - end - end - - ## - # A very simple reporter that prints the "dots" during the run. - # - # This is added to the top-level CompositeReporter at the start of - # the run. If you want to change the output of minitest via a - # plugin, pull this out of the composite and replace it with your - # own. - - class ProgressReporter < Reporter - def prerecord klass, name #:nodoc: - if options[:verbose] then - io.print "%s#%s = " % [klass, name] - io.flush - end - end - - def record result # :nodoc: - io.print "%.2f s = " % [result.time] if options[:verbose] - io.print result.result_code - io.puts if options[:verbose] - end - end - - ## - # A reporter that gathers statistics about a test run. Does not do - # any IO because meant to be used as a parent class for a reporter - # that does. - # - # If you want to create an entirely different type of output (eg, - # CI, HTML, etc), this is the place to start. - - class StatisticsReporter < Reporter - # :stopdoc: - attr_accessor :assertions - attr_accessor :count - attr_accessor :results - attr_accessor :start_time - attr_accessor :total_time - attr_accessor :failures - attr_accessor :errors - attr_accessor :skips - # :startdoc: - - def initialize io = $stdout, options = {} # :nodoc: - super - - self.assertions = 0 - self.count = 0 - self.results = [] - self.start_time = nil - self.total_time = nil - self.failures = nil - self.errors = nil - self.skips = nil - end - - def passed? # :nodoc: - results.all?(&:skipped?) - end - - def start # :nodoc: - self.start_time = Minitest.clock_time - end - - def record result # :nodoc: - self.count += 1 - self.assertions += result.assertions - - results << result if not result.passed? or result.skipped? - end - - def report # :nodoc: - aggregate = results.group_by { |r| r.failure.class } - aggregate.default = [] # dumb. group_by should provide this - - self.total_time = Minitest.clock_time - start_time - self.failures = aggregate[Assertion].size - self.errors = aggregate[UnexpectedError].size - self.skips = aggregate[Skip].size - end - end - - ## - # A reporter that prints the header, summary, and failure details at - # the end of the run. - # - # This is added to the top-level CompositeReporter at the start of - # the run. If you want to change the output of minitest via a - # plugin, pull this out of the composite and replace it with your - # own. - - class SummaryReporter < StatisticsReporter - # :stopdoc: - attr_accessor :sync - attr_accessor :old_sync - # :startdoc: - - def start # :nodoc: - super - - io.puts "Run options: #{options[:args]}" - io.puts - io.puts "# Running:" - io.puts - - self.sync = io.respond_to? :"sync=" # stupid emacs - self.old_sync, io.sync = io.sync, true if self.sync - end - - def report # :nodoc: - super - - io.sync = self.old_sync - - io.puts unless options[:verbose] # finish the dots - io.puts - io.puts statistics - aggregated_results io - io.puts summary - end - - def statistics # :nodoc: - "Finished in %.6fs, %.4f runs/s, %.4f assertions/s." % - [total_time, count / total_time, assertions / total_time] - end - - def aggregated_results io # :nodoc: - filtered_results = results.dup - filtered_results.reject!(&:skipped?) unless options[:verbose] - - filtered_results.each_with_index { |result, i| - io.puts "\n%3d) %s" % [i+1, result] - } - io.puts - io - end - - def to_s # :nodoc: - aggregated_results(StringIO.new(binary_string)).string - end - - def summary # :nodoc: - extra = "" - - extra = "\n\nYou have skipped tests. Run with --verbose for details." if - results.any?(&:skipped?) unless options[:verbose] or ENV["MT_NO_SKIP_MSG"] - - "%d runs, %d assertions, %d failures, %d errors, %d skips%s" % - [count, assertions, failures, errors, skips, extra] - end - - private - - if '<3'.respond_to? :b - def binary_string; ''.b; end - else - def binary_string; ''.force_encoding(Encoding::ASCII_8BIT); end - end - end - - ## - # Dispatch to multiple reporters as one. - - class CompositeReporter < AbstractReporter - ## - # The list of reporters to dispatch to. - - attr_accessor :reporters - - def initialize *reporters # :nodoc: - super() - self.reporters = reporters - end - - def io # :nodoc: - reporters.first.io - end - - ## - # Add another reporter to the mix. - - def << reporter - self.reporters << reporter - end - - def passed? # :nodoc: - self.reporters.all?(&:passed?) - end - - def start # :nodoc: - self.reporters.each(&:start) - end - - def prerecord klass, name # :nodoc: - self.reporters.each do |reporter| - # TODO: remove conditional for minitest 6 - reporter.prerecord klass, name if reporter.respond_to? :prerecord - end - end - - def record result # :nodoc: - self.reporters.each do |reporter| - reporter.record result - end - end - - def report # :nodoc: - self.reporters.each(&:report) - end - end - - ## - # Represents run failures. - - class Assertion < Exception - def error # :nodoc: - self - end - - ## - # Where was this run before an assertion was raised? - - def location - last_before_assertion = "" - self.backtrace.reverse_each do |s| - last_before_assertion = s - end - end - - def result_code # :nodoc: - result_label[0, 1] - end - - def result_label # :nodoc: - "Failure" - end - end - - ## - # Assertion raised when skipping a run. - - class Skip < Assertion - def result_label # :nodoc: - "Skipped" - end - end - - ## - # Assertion wrapping an unexpected error that was raised during a run. - - class UnexpectedError < Assertion - attr_accessor :exception # :nodoc: - - def initialize exception # :nodoc: - super "Unexpected exception" - self.exception = exception - end - - def backtrace # :nodoc: - self.exception.backtrace - end - - def error # :nodoc: - self.exception - end - - def message # :nodoc: - bt = Minitest.filter_backtrace(self.backtrace).join "\n " - "#{self.exception.class}: #{self.exception.message}\n #{bt}" - end - - def result_label # :nodoc: - "Error" - end - end - - ## - # Provides a simple set of guards that you can use in your tests - # to skip execution if it is not applicable. These methods are - # mixed into Test as both instance and class methods so you - # can use them inside or outside of the test methods. - # - # def test_something_for_mri - # skip "bug 1234" if jruby? - # # ... - # end - # - # if windows? then - # # ... lots of test methods ... - # end - - module Guard - - ## - # Is this running on jruby? - - def jruby? platform = RUBY_PLATFORM - "java" == platform - end - - ## - # Is this running on maglev? - - def maglev? platform = defined?(RUBY_ENGINE) && RUBY_ENGINE - "maglev" == platform - end - - ## - # Is this running on mri? - - def mri? platform = RUBY_DESCRIPTION - /^ruby/ =~ platform - end - - ## - # Is this running on rubinius? - - def rubinius? platform = defined?(RUBY_ENGINE) && RUBY_ENGINE - "rbx" == platform - end - - ## - # Is this running on windows? - - def windows? platform = RUBY_PLATFORM - /mswin|mingw/ =~ platform - end - end - - ## - # The standard backtrace filter for minitest. - # - # See Minitest.backtrace_filter=. - - class BacktraceFilter - - MT_RE = %r%lib/minitest% #:nodoc: - - ## - # Filter +bt+ to something useful. Returns the whole thing if $DEBUG. - - def filter bt - return ["No backtrace"] unless bt - - return bt.dup if $DEBUG - - new_bt = bt.take_while { |line| line !~ MT_RE } - new_bt = bt.select { |line| line !~ MT_RE } if new_bt.empty? - new_bt = bt.dup if new_bt.empty? - - new_bt - end - end - - self.backtrace_filter = BacktraceFilter.new - - def self.run_one_method klass, method_name # :nodoc: - result = klass.new(method_name).run - raise "#{klass}#run _must_ return self" unless klass === result - result - end - - # :stopdoc: - - if defined? Process::CLOCK_MONOTONIC # :nodoc: - def self.clock_time - Process.clock_gettime Process::CLOCK_MONOTONIC - end - else - def self.clock_time - Time.now - end - end - - # :startdoc: -end - -require "minitest/test" diff --git a/src/main/antlr4/depends/extractor/ruby/test/moduletest.rb b/src/main/antlr4/depends/extractor/ruby/test/moduletest.rb deleted file mode 100644 index 951c1a8..0000000 --- a/src/main/antlr4/depends/extractor/ruby/test/moduletest.rb +++ /dev/null @@ -1,13 +0,0 @@ -module Week - FIRST_DAY = "Sunday" - def Week.weeks_in_month - puts "You have four weeks in a month" - end - def Week.weeks_in_year - puts "You have 52 weeks in a year" - end -end - -class F -include Week -end diff --git a/src/main/antlr4/depends/extractor/ruby/test/newinvoke.rb b/src/main/antlr4/depends/extractor/ruby/test/newinvoke.rb deleted file mode 100644 index 2c2eb2d..0000000 --- a/src/main/antlr4/depends/extractor/ruby/test/newinvoke.rb +++ /dev/null @@ -1 +0,0 @@ - self.parallel_executor = Parallel::Executor.new((ENV["N"] || 2).to_i) diff --git a/src/main/antlr4/depends/extractor/ruby/test/next.rb b/src/main/antlr4/depends/extractor/ruby/test/next.rb deleted file mode 100644 index 6173a00..0000000 --- a/src/main/antlr4/depends/extractor/ruby/test/next.rb +++ /dev/null @@ -1,9 +0,0 @@ -Gem.find_files("minitest/*_plugin.rb").each do |plugin_path| - name = File.basename plugin_path, "_plugin.rb" - - next if seen[name] - seen[name] = true - - require plugin_path - self.extensions << name - end diff --git a/src/main/antlr4/depends/extractor/ruby/test/quoted_string.rb b/src/main/antlr4/depends/extractor/ruby/test/quoted_string.rb deleted file mode 100644 index 48bb818..0000000 --- a/src/main/antlr4/depends/extractor/ruby/test/quoted_string.rb +++ /dev/null @@ -1,7 +0,0 @@ -puts %w{abc 123} - -puts "abc" - -puts %s|123d aaad afa }{[ | -puts "helo" - diff --git a/src/main/antlr4/depends/extractor/ruby/test/quoted_string_example.rb b/src/main/antlr4/depends/extractor/ruby/test/quoted_string_example.rb deleted file mode 100755 index 175f60b..0000000 --- a/src/main/antlr4/depends/extractor/ruby/test/quoted_string_example.rb +++ /dev/null @@ -1,9 +0,0 @@ -class TestSchemaNormalization < Test::Unit::TestCase - def test_primitives - %w[null boolean string bytes int long float double].each do |type| - canonical_form = Avro::SchemaNormalization.to_parsing_form(schema) - end - end - - -end diff --git a/src/main/antlr4/depends/extractor/ruby/test/range.rb b/src/main/antlr4/depends/extractor/ruby/test/range.rb deleted file mode 100644 index 7e04eb2..0000000 --- a/src/main/antlr4/depends/extractor/ruby/test/range.rb +++ /dev/null @@ -1,8 +0,0 @@ -for rs in promotable_schemas[(i + 1)..-1] - readers_schema = Avro::Schema.parse(rs) - writer, enc, dw = write_datum(datum_to_write, writers_schema) - datum_read = read_datum(writer, writers_schema, readers_schema) - if datum_read != datum_to_write - incorrect += 1 - end - end diff --git a/src/main/antlr4/depends/extractor/ruby/test/regex2.rb b/src/main/antlr4/depends/extractor/ruby/test/regex2.rb deleted file mode 100644 index d94e7d9..0000000 --- a/src/main/antlr4/depends/extractor/ruby/test/regex2.rb +++ /dev/null @@ -1,3 +0,0 @@ -options[:args] = orig_args.map { |s| - s =~ /[\s|&<>$()]/ ? s.inspect : s - }.join " " diff --git a/src/main/antlr4/depends/extractor/ruby/test/regex3.rb b/src/main/antlr4/depends/extractor/ruby/test/regex3.rb deleted file mode 100644 index 6fb1172..0000000 --- a/src/main/antlr4/depends/extractor/ruby/test/regex3.rb +++ /dev/null @@ -1 +0,0 @@ - if id = @scanner.scan(/\/\/ \d+\n/) ; end diff --git a/src/main/antlr4/depends/extractor/ruby/test/require.rb b/src/main/antlr4/depends/extractor/ruby/test/require.rb deleted file mode 100644 index ab0111b..0000000 --- a/src/main/antlr4/depends/extractor/ruby/test/require.rb +++ /dev/null @@ -1 +0,0 @@ -require 'abc' diff --git a/src/main/antlr4/depends/extractor/ruby/test/rescure_retry.rb b/src/main/antlr4/depends/extractor/ruby/test/rescure_retry.rb deleted file mode 100644 index 86b82a7..0000000 --- a/src/main/antlr4/depends/extractor/ruby/test/rescure_retry.rb +++ /dev/null @@ -1,35 +0,0 @@ -#!/usr/bin/ruby -# -*- coding: UTF-8 -*- - -for i in 1..5 - retry if i > 2 - puts "局部变量的值为 #{i}" -end - - -#!/usr/bin/ruby - -begin - puts 'I am before the raise.' - raise 'An error has occurred.' - raise '1.',a,10 - raise '1.',a,10 if i>2 - puts 'I am after the raise.' - puts 'I am rescued.' -rescure - puts 'I am rescued.' -ensure - puts 'I am rescued.' - puts 'I am rescued.' -end - -puts 'I am after the begin block.' - -begin - response = call(local_message, request) - rescue AvroRemoteError => e - error = e - rescue Exception => e - error = AvroRemoteError.new(e.to_s) -end - diff --git a/src/main/antlr4/depends/extractor/ruby/test/single_char_string.rb b/src/main/antlr4/depends/extractor/ruby/test/single_char_string.rb deleted file mode 100644 index e06070d..0000000 --- a/src/main/antlr4/depends/extractor/ruby/test/single_char_string.rb +++ /dev/null @@ -1,34 +0,0 @@ -test_ok(?a == ?a) -test_ok(?\C-a == "\1") -test_ok(?\C-? == "\1") -test_ok(?\M-a == "\341") -test_ok(?\M-\C-a == "\201") -test_ok("a".upcase![0] == ?A) -test_ok(?\C-! == "\1") -test_ok(?\C-# == "\1") -test_ok(?\C-$ == "\1") -test_ok(?\C-% == "\1") -test_ok(?\C-& == "\1") -test_ok(?\C-' == "\1") -test_ok(?\C-( == "\1") -test_ok(?\C-) == "\1") -test_ok(?\C-* == "\1") -test_ok(?\C-+ == "\1") -test_ok(?\C-, == "\1") -test_ok(?\C-- == "\1") -test_ok(?\C-. == "\1") -test_ok(?\C-/ == "\1") -test_ok(?\C-: == "\1") -test_ok(?\C-; == "\1") -test_ok(?\C-< == "\1") -test_ok(?\C-= == "\1") -test_ok(?\C-> == "\1") -test_ok(?\C-? == "\1") -test_ok(?\C-@ == "\1") -test_ok(?\C-[ == "\1") -test_ok(?\C-\ == "\1") -test_ok(?\C-] == "\1") -test_ok(?\C-^ == "\1") -test_ok(?\C-` == "\1") -test_ok(?\C-~ == "\1") - diff --git a/src/main/antlr4/depends/extractor/ruby/test/special_func_name.rb b/src/main/antlr4/depends/extractor/ruby/test/special_func_name.rb deleted file mode 100644 index 163e6eb..0000000 --- a/src/main/antlr4/depends/extractor/ruby/test/special_func_name.rb +++ /dev/null @@ -1,11 +0,0 @@ -class Result - attr_reader :errors - - def initialize - @errors = [] - end - - def << - @errors = [] - end -end diff --git a/src/main/antlr4/depends/extractor/ruby/test/string.rb b/src/main/antlr4/depends/extractor/ruby/test/string.rb deleted file mode 100644 index 01caedf..0000000 --- a/src/main/antlr4/depends/extractor/ruby/test/string.rb +++ /dev/null @@ -1,2 +0,0 @@ -Set.new(%w[null boolean string bytes int long float double]) - diff --git a/src/main/antlr4/depends/extractor/ruby/test/t.rb b/src/main/antlr4/depends/extractor/ruby/test/t.rb deleted file mode 100644 index 2c1a613..0000000 --- a/src/main/antlr4/depends/extractor/ruby/test/t.rb +++ /dev/null @@ -1,25 +0,0 @@ -class RandomData - def nextdata(schm, d=0) - case schm.type_sym - when :bytes - randstr(BYTEPOOL) - when :null - nil - when :array - arr = [] - len = rand(5) + 2 - d - len = 0 if len < 0 - len.times{ arr << nextdata(schm.items, d+1) } - arr - when :map - map = {} - len = rand(5) + 2 - d - len = 0 if len < 0 - len.times do - map[nextdata(Avro::Schema::PrimitiveSchema.new(:string))] = nextdata(schm.values, d+1) - end - map - end - end - -end diff --git a/src/main/antlr4/depends/extractor/ruby/test/t1.rb b/src/main/antlr4/depends/extractor/ruby/test/t1.rb deleted file mode 100644 index 0f520aa..0000000 --- a/src/main/antlr4/depends/extractor/ruby/test/t1.rb +++ /dev/null @@ -1,16 +0,0 @@ -#!/usr/bin/ruby -print <<-EOF - This is the first way of creating - here document ie. multiple line string. -EOF - -print <<-"EOF"; # 与上面相同 - This is the second way of creating - here document ie. multiple line string. -EOF - -print <<`EOC` # 执行命令 - echo hi there - echo lo there -EOC - diff --git a/src/main/antlr4/depends/extractor/ruby/test/t10.rb b/src/main/antlr4/depends/extractor/ruby/test/t10.rb deleted file mode 100644 index 1d00653..0000000 --- a/src/main/antlr4/depends/extractor/ruby/test/t10.rb +++ /dev/null @@ -1,9 +0,0 @@ - while true do - writer.write() - (n >>= 7) - end - - while (n & ~0x7F) != 0 - @writer.write(((n & 0x7f) | 0x80).chr) - n >>= 7 - end diff --git a/src/main/antlr4/depends/extractor/ruby/test/t11.rb b/src/main/antlr4/depends/extractor/ruby/test/t11.rb deleted file mode 100644 index c00b335..0000000 --- a/src/main/antlr4/depends/extractor/ruby/test/t11.rb +++ /dev/null @@ -1 +0,0 @@ -a >>= 8 diff --git a/src/main/antlr4/depends/extractor/ruby/test/t12.rb b/src/main/antlr4/depends/extractor/ruby/test/t12.rb deleted file mode 100644 index f4b823b..0000000 --- a/src/main/antlr4/depends/extractor/ruby/test/t12.rb +++ /dev/null @@ -1,6 +0,0 @@ -test_check "assignment" - -a=[]; a[0] ||= "bar"; -test_ok(a[0] == "bar") -h={}; h["foo"] ||= "bar"; -test_ok(h["foo"] == "bar") diff --git a/src/main/antlr4/depends/extractor/ruby/test/t3.rb b/src/main/antlr4/depends/extractor/ruby/test/t3.rb deleted file mode 100644 index 909a9d8..0000000 --- a/src/main/antlr4/depends/extractor/ruby/test/t3.rb +++ /dev/null @@ -1,16 +0,0 @@ - def read_array(writers_schema, readers_schema, decoder) - read_items = [] - block_count = decoder.read_long - while block_count != 0 - if block_count < 0 - block_count = -block_count - block_size = decoder.read_long - end - block_count.times do - read_items << read_data(writers_schema.items, - readers_schema.items, - decoder) - end - block_count = decoder.read_long - end - end diff --git a/src/main/antlr4/depends/extractor/ruby/test/t4.rb b/src/main/antlr4/depends/extractor/ruby/test/t4.rb deleted file mode 100644 index eea0f41..0000000 --- a/src/main/antlr4/depends/extractor/ruby/test/t4.rb +++ /dev/null @@ -1,38 +0,0 @@ - def read(decoder) - self.readers_schema = writers_schema unless readers_schema - read_data(writers_schema, readers_schema, decoder) - end - - def read_data(writers_schema, readers_schema, decoder) - # schema matching - unless self.class.match_schemas(writers_schema, readers_schema) - raise SchemaMatchException.new(writers_schema, readers_schema) - end - - # schema resolution: reader's schema is a union, writer's - # schema is not - if writers_schema.type_sym != :union && readers_schema.type_sym == :union - rs = readers_schema.schemas.find{|s| - self.class.match_schemas(writers_schema, s) - } - return read_data(writers_schema, rs, decoder) if rs - raise SchemaMatchException.new(writers_schema, readers_schema) - end - case writers_schema.type_sym - when :union; read_union(writers_schema, readers_schema, decoder) - when :record, :error, :request; read_record(writers_schema, readers_schema, decoder) - else - raise AvroError, "Cannot read unknown schema type: #{writers_schema.type}" - end - end - - def read_enum(writers_schema, readers_schema, decoder) - - unless readers_schema.symbols.include?(read_symbol) - # 'unset' here - end - - read_symbol - end - - diff --git a/src/main/antlr4/depends/extractor/ruby/test/t6.rb b/src/main/antlr4/depends/extractor/ruby/test/t6.rb deleted file mode 100644 index 0708aca..0000000 --- a/src/main/antlr4/depends/extractor/ruby/test/t6.rb +++ /dev/null @@ -1,10 +0,0 @@ -def self.make_field_objects(field_data, names, namespace=nil) - field_objects, field_names = [], Set.new - field_data.each_with_index do |field, i| - if field.respond_to?(:[]) # TODO(jmhodges) wtffffff - raise SchemaParseError, "Not a valid field: #{field}" - end - field_objects << new_field - end - field_objects - end diff --git a/src/main/antlr4/depends/extractor/ruby/test/t8.rb b/src/main/antlr4/depends/extractor/ruby/test/t8.rb deleted file mode 100644 index c2d40ca..0000000 --- a/src/main/antlr4/depends/extractor/ruby/test/t8.rb +++ /dev/null @@ -1 +0,0 @@ -def r(val); a = yield; test_ok(a == val, 2); end diff --git a/src/main/antlr4/depends/extractor/ruby/test/t9.rb b/src/main/antlr4/depends/extractor/ruby/test/t9.rb deleted file mode 100644 index a201352..0000000 --- a/src/main/antlr4/depends/extractor/ruby/test/t9.rb +++ /dev/null @@ -1,5 +0,0 @@ -if x == x then - a -else -b -end diff --git a/src/main/antlr4/depends/extractor/ruby/test/test.rb b/src/main/antlr4/depends/extractor/ruby/test/test.rb deleted file mode 100755 index 25d52ca..0000000 --- a/src/main/antlr4/depends/extractor/ruby/test/test.rb +++ /dev/null @@ -1,2367 +0,0 @@ -#! /usr/bin/env ruby -# -*- coding: us-ascii -*- - -$testnum=0 -$ntest=0 -$failed = 0 -class Progress - def initialize - @color = nil - @tty = nil - @quiet = nil - @verbose = nil - ARGV.each do |arg| - case arg - when /\A--color(?:=(?:always|(auto)|(never)|(.*)))?\z/ - warn "unknown --color argument: #$3" if $3 - @color = $1 ? nil : !$2 - when /\A--tty(=(?:yes|(no)|(.*)))?\z/ - warn "unknown --tty argument: #$3" if $3 - @tty = !$1 || !$2 - true - when /\A-(q|-quiet)\z/ - @quiet = true - when /\A-(v|-verbose)\z/ - @verbose = true - end - end - @tty = STDERR.tty? && !STDOUT.tty? && /dumb/ !~ ENV["TERM"] if @tty.nil? - @eol = @tty && !@verbose ? "\r\e[K\r" : "\n" - case @color - when nil - @color = @tty - end - if @color - # dircolors-like style - colors = (colors = ENV['TEST_COLORS']) ? Hash[colors.scan(/(\w+)=([^:\n]*)/)] : {} - begin - File.read(File.join(__dir__, "../test/colors")).scan(/(\w+)=([^:\n]*)/) do |n, c| - colors[n] ||= c - end - rescue - end - @passed = "\e[;#{colors["pass"] || "32"}m" - @failed = "\e[;#{colors["fail"] || "31"}m" - @reset = "\e[m" - else - @passed = @failed = @reset = "" - end - extend(Rotator) if @tty - end - - def passed_string - "." - end - def failed_string - "#{@failed}F#{@reset}" - end - def init_string - end - def finish_string - if @quiet - @eol - else - "#{@passed}#{@ok ? 'OK' : ''} #{$testnum}#{@reset}#{@eol}" - end - end - def pass - STDERR.print passed_string - end - def fail - @ok = false - STDERR.print failed_string - end - def init - @ok = true - STDERR.print init_string - end - def finish - STDERR.print finish_string - end - - module Rotator - ROTATOR = %w[- \\ | /] - BS = "\b" * ROTATOR[0].size - def passed_string - "#{BS}#{ROTATOR[(@count += 1) % ROTATOR.size]}" - end - def failed_string - "#{BS}#{super}#{ROTATOR[@count % ROTATOR.size]}" - end - def init_string - @count = 0 - " " - end - def finish_string - s = "#{BS}#{' ' * BS.size}#{BS}#{super}" - s.gsub!(/\n/, "\r\e[2K\r") if @quiet - s - end - end -end -PROGRESS = Progress.new - -def test_check(what) - unless $ntest.zero? - PROGRESS.finish - end - STDERR.print "#{$0}:#{what} " - PROGRESS.init - $what = what - $testnum = 0 -end - -def test_ok(cond,n=1) - $testnum+=1 - $ntest+=1 - where = (st = caller(n)) ? st[0] : "caller error! (n=#{n}, trace=#{caller(0).join(', ')}" - if cond - PROGRESS.pass - printf "ok %d (%s)\n", $testnum, where - else - PROGRESS.fail - printf "not ok %s %d -- %s\n", $what, $testnum, where - $failed+=1 - end - STDOUT.flush - STDERR.flush -end - -# make sure conditional operators work - -test_check "assignment" - -a=[]; a[0] ||= "bar"; -test_ok(a[0] == "bar") -h={}; h["foo"] ||= "bar"; -test_ok(h["foo"] == "bar") - -aa = 5 -aa ||= 25 -test_ok(aa == 5) -bb ||= 25 -test_ok(bb == 25) -cc &&=33 -test_ok(cc == nil) -cc = 5 -cc &&=44 -test_ok(cc == 44) - -a = nil; test_ok(a == nil) -a = 1; test_ok(a == 1) -a = []; test_ok(a == []) -a = [1]; test_ok(a == [1]) -a = [nil]; test_ok(a == [nil]) -a = [[]]; test_ok(a == [[]]) -a = [1,2]; test_ok(a == [1,2]) -a = [*[]]; test_ok(a == []) -a = [*[1]]; test_ok(a == [1]) -a = [*[1,2]]; test_ok(a == [1,2]) - -a = *[]; test_ok(a == []) -a = *[1]; test_ok(a == [1]) -a = *[nil]; test_ok(a == [nil]) -a = *[[]]; test_ok(a == [[]]) -a = *[1,2]; test_ok(a == [1,2]) -a = *[*[]]; test_ok(a == []) -a = *[*[1]]; test_ok(a == [1]) -a = *[*[1,2]]; test_ok(a == [1,2]) - -a, = nil; test_ok(a == nil) -a, = 1; test_ok(a == 1) -a, = []; test_ok(a == nil) -a, = [1]; test_ok(a == 1) -a, = [nil]; test_ok(a == nil) -a, = [[]]; test_ok(a == []) -a, = 1,2; test_ok(a == 1) -a, = [1,2]; test_ok(a == 1) -a, = [*[]]; test_ok(a == nil) -a, = [*[1]]; test_ok(a == 1) -a, = *[1,2]; test_ok(a == 1) -a, = [*[1,2]]; test_ok(a == 1) - -a, = *[]; test_ok(a == nil) -a, = *[1]; test_ok(a == 1) -a, = *[nil]; test_ok(a == nil) -a, = *[[]]; test_ok(a == []) -a, = *[1,2]; test_ok(a == 1) -a, = *[*[]]; test_ok(a == nil) -a, = *[*[1]]; test_ok(a == 1) -a, = *[*[1,2]]; test_ok(a == 1) - -*a = nil; test_ok(a == [nil]) -*a = 1; test_ok(a == [1]) -*a = []; test_ok(a == []) -*a = [1]; test_ok(a == [1]) -*a = [nil]; test_ok(a == [nil]) -*a = [[]]; test_ok(a == [[]]) -*a = [1,2]; test_ok(a == [1,2]) -*a = [*[]]; test_ok(a == []) -*a = [*[1]]; test_ok(a == [1]) -*a = [*[1,2]]; test_ok(a == [1,2]) - -*a = *[]; test_ok(a == []) -*a = *[1]; test_ok(a == [1]) -*a = *[nil]; test_ok(a == [nil]) -*a = *[[]]; test_ok(a == [[]]) -*a = *[1,2]; test_ok(a == [1,2]) -*a = *[*[]]; test_ok(a == []) -*a = *[*[1]]; test_ok(a == [1]) -*a = *[*[1,2]]; test_ok(a == [1,2]) - -a,b,*c = nil; test_ok([a,b,c] == [nil,nil,[]]) -a,b,*c = 1; test_ok([a,b,c] == [1,nil,[]]) -a,b,*c = []; test_ok([a,b,c] == [nil,nil,[]]) -a,b,*c = [1]; test_ok([a,b,c] == [1,nil,[]]) -a,b,*c = [nil]; test_ok([a,b,c] == [nil,nil,[]]) -a,b,*c = [[]]; test_ok([a,b,c] == [[],nil,[]]) -a,b,*c = [1,2]; test_ok([a,b,c] == [1,2,[]]) -a,b,*c = [*[]]; test_ok([a,b,c] == [nil,nil,[]]) -a,b,*c = [*[1]]; test_ok([a,b,c] == [1,nil,[]]) -a,b,*c = [*[1,2]]; test_ok([a,b,c] == [1,2,[]]) - -a,b,*c = *[]; test_ok([a,b,c] == [nil,nil,[]]) -a,b,*c = *[1]; test_ok([a,b,c] == [1,nil,[]]) -a,b,*c = *[nil]; test_ok([a,b,c] == [nil,nil,[]]) -a,b,*c = *[[]]; test_ok([a,b,c] == [[],nil,[]]) -a,b,*c = *[1,2]; test_ok([a,b,c] == [1,2,[]]) -a,b,*c = *[*[]]; test_ok([a,b,c] == [nil,nil,[]]) -a,b,*c = *[*[1]]; test_ok([a,b,c] == [1,nil,[]]) -a,b,*c = *[*[1,2]]; test_ok([a,b,c] == [1,2,[]]) - -def f; yield nil; end; f {|a| test_ok(a == nil)} -def f; yield 1; end; f {|a| test_ok(a == 1)} -def f; yield []; end; f {|a| test_ok(a == [])} -def f; yield [1]; end; f {|a| test_ok(a == [1])} -def f; yield [nil]; end; f {|a| test_ok(a == [nil])} -def f; yield [[]]; end; f {|a| test_ok(a == [[]])} -def f; yield [*[]]; end; f {|a| test_ok(a == [])} -def f; yield [*[1]]; end; f {|a| test_ok(a == [1])} -def f; yield [*[1,2]]; end; f {|a| test_ok(a == [1,2])} -def f; yield *[]; end; f {|a| test_ok(a == nil)} -def f; yield *[1]; end; f {|a| test_ok(a == 1)} -def f; yield *[nil]; end; f {|a| test_ok(a == nil)} -def f; yield *[[]]; end; f {|a| test_ok(a == [])} -def f; yield *[*[]]; end; f {|a| test_ok(a == nil)} -def f; yield *[*[1]]; end; f {|a| test_ok(a == 1)} -def f; yield *[*[1,2]]; end; f {|a| test_ok(a == 1)} - -def f; yield; end; f {|a,| test_ok(a == nil)} -def f; yield nil; end; f {|a,| test_ok(a == nil)} -def f; yield 1; end; f {|a,| test_ok(a == 1)} -def f; yield []; end; f {|a,| test_ok(a == nil)} -def f; yield [1]; end; f {|a,| test_ok(a == 1)} -def f; yield [nil]; end; f {|a,| test_ok(a == nil)} -def f; yield [[]]; end; f {|a,| test_ok(a == [])} -def f; yield [*[]]; end; f {|a,| test_ok(a == nil)} -def f; yield [*[1]]; end; f {|a,| test_ok(a == 1)} -def f; yield [*[1,2]]; end; f {|a,| test_ok(a == 1)} - -def f; yield *[]; end; f {|a,| test_ok(a == nil)} -def f; yield *[1]; end; f {|a,| test_ok(a == 1)} -def f; yield *[nil]; end; f {|a,| test_ok(a == nil)} -def f; yield *[[]]; end; f {|a,| test_ok(a == nil)} -def f; yield *[*[]]; end; f {|a,| test_ok(a == nil)} -def f; yield *[*[1]]; end; f {|a,| test_ok(a == 1)} -def f; yield *[*[1,2]]; end; f {|a,| test_ok(a == 1)} - -def f; yield; end; f {|*a| test_ok(a == [])} -def f; yield nil; end; f {|*a| test_ok(a == [nil])} -def f; yield 1; end; f {|*a| test_ok(a == [1])} -def f; yield []; end; f {|*a| test_ok(a == [[]])} -def f; yield [1]; end; f {|*a| test_ok(a == [[1]])} -def f; yield [nil]; end; f {|*a| test_ok(a == [[nil]])} -def f; yield [[]]; end; f {|*a| test_ok(a == [[[]]])} -def f; yield [1,2]; end; f {|*a| test_ok(a == [[1,2]])} -def f; yield [*[]]; end; f {|*a| test_ok(a == [[]])} -def f; yield [*[1]]; end; f {|*a| test_ok(a == [[1]])} -def f; yield [*[1,2]]; end; f {|*a| test_ok(a == [[1,2]])} - -def f; yield *[]; end; f {|*a| test_ok(a == [])} -def f; yield *[1]; end; f {|*a| test_ok(a == [1])} -def f; yield *[nil]; end; f {|*a| test_ok(a == [nil])} -def f; yield *[[]]; end; f {|*a| test_ok(a == [[]])} -def f; yield *[*[]]; end; f {|*a| test_ok(a == [])} -def f; yield *[*[1]]; end; f {|*a| test_ok(a == [1])} -def f; yield *[*[1,2]]; end; f {|*a| test_ok(a == [1,2])} - -def f; yield; end; f {|a,b,*c| test_ok([a,b,c] == [nil,nil,[]])} -def f; yield nil; end; f {|a,b,*c| test_ok([a,b,c] == [nil,nil,[]])} -def f; yield 1; end; f {|a,b,*c| test_ok([a,b,c] == [1,nil,[]])} -def f; yield []; end; f {|a,b,*c| test_ok([a,b,c] == [nil,nil,[]])} -def f; yield [1]; end; f {|a,b,*c| test_ok([a,b,c] == [1,nil,[]])} -def f; yield [nil]; end; f {|a,b,*c| test_ok([a,b,c] == [nil,nil,[]])} -def f; yield [[]]; end; f {|a,b,*c| test_ok([a,b,c] == [[],nil,[]])} -def f; yield [*[]]; end; f {|a,b,*c| test_ok([a,b,c] == [nil,nil,[]])} -def f; yield [*[1]]; end; f {|a,b,*c| test_ok([a,b,c] == [1,nil,[]])} -def f; yield [*[1,2]]; end; f {|a,b,*c| test_ok([a,b,c] == [1,2,[]])} - -def f; yield *[]; end; f {|a,b,*c| test_ok([a,b,c] == [nil,nil,[]])} -def f; yield *[1]; end; f {|a,b,*c| test_ok([a,b,c] == [1,nil,[]])} -def f; yield *[nil]; end; f {|a,b,*c| test_ok([a,b,c] == [nil,nil,[]])} -def f; yield *[[]]; end; f {|a,b,*c| test_ok([a,b,c] == [nil,nil,[]])} -def f; yield *[*[]]; end; f {|a,b,*c| test_ok([a,b,c] == [nil,nil,[]])} -def f; yield *[*[1]]; end; f {|a,b,*c| test_ok([a,b,c] == [1,nil,[]])} -def f; yield *[*[1,2]]; end; f {|a,b,*c| test_ok([a,b,c] == [1,2,[]])} - -def r; return; end; a = r(); test_ok(a == nil) -def r; return nil; end; a = r(); test_ok(a == nil) -def r; return 1; end; a = r(); test_ok(a == 1) -def r; return []; end; a = r(); test_ok(a == []) -def r; return [1]; end; a = r(); test_ok(a == [1]) -def r; return [nil]; end; a = r(); test_ok(a == [nil]) -def r; return [[]]; end; a = r(); test_ok(a == [[]]) -def r; return [*[]]; end; a = r(); test_ok(a == []) -def r; return [*[1]]; end; a = r(); test_ok(a == [1]) -def r; return [*[1,2]]; end; a = r(); test_ok(a == [1,2]) - -def r; return *[]; end; a = r(); test_ok(a == []) -def r; return *[1]; end; a = r(); test_ok(a == [1]) -def r; return *[nil]; end; a = r(); test_ok(a == [nil]) -def r; return *[[]]; end; a = r(); test_ok(a == [[]]) -def r; return *[*[]]; end; a = r(); test_ok(a == []) -def r; return *[*[1]]; end; a = r(); test_ok(a == [1]) -def r; return *[*[1,2]]; end; a = r(); test_ok(a == [1,2]) - -def r; return *[[]]; end; a = *r(); test_ok(a == [[]]) -def r; return *[*[1,2]]; end; a = *r(); test_ok(a == [1,2]) - -def r; return; end; *a = r(); test_ok(a == [nil]) -def r; return nil; end; *a = r(); test_ok(a == [nil]) -def r; return 1; end; *a = r(); test_ok(a == [1]) -def r; return []; end; *a = r(); test_ok(a == []) -def r; return [1]; end; *a = r(); test_ok(a == [1]) -def r; return [nil]; end; *a = r(); test_ok(a == [nil]) -def r; return [[]]; end; *a = r(); test_ok(a == [[]]) -def r; return [1,2]; end; *a = r(); test_ok(a == [1,2]) -def r; return [*[]]; end; *a = r(); test_ok(a == []) -def r; return [*[1]]; end; *a = r(); test_ok(a == [1]) -def r; return [*[1,2]]; end; *a = r(); test_ok(a == [1,2]) - -def r; return *[]; end; *a = r(); test_ok(a == []) -def r; return *[1]; end; *a = r(); test_ok(a == [1]) -def r; return *[nil]; end; *a = r(); test_ok(a == [nil]) -def r; return *[[]]; end; *a = r(); test_ok(a == [[]]) -def r; return *[1,2]; end; *a = r(); test_ok(a == [1,2]) -def r; return *[*[]]; end; *a = r(); test_ok(a == []) -def r; return *[*[1]]; end; *a = r(); test_ok(a == [1]) -def r; return *[*[1,2]]; end; *a = r(); test_ok(a == [1,2]) - -def r; return *[[]]; end; *a = *r(); test_ok(a == [[]]) -def r; return *[1,2]; end; *a = *r(); test_ok(a == [1,2]) -def r; return *[*[1,2]]; end; *a = *r(); test_ok(a == [1,2]) - -def r; return; end; a,b,*c = r(); test_ok([a,b,c] == [nil,nil,[]]) -def r; return nil; end; a,b,*c = r(); test_ok([a,b,c] == [nil,nil,[]]) -def r; return 1; end; a,b,*c = r(); test_ok([a,b,c] == [1,nil,[]]) -def r; return []; end; a,b,*c = r(); test_ok([a,b,c] == [nil,nil,[]]) -def r; return [1]; end; a,b,*c = r(); test_ok([a,b,c] == [1,nil,[]]) -def r; return [nil]; end; a,b,*c = r(); test_ok([a,b,c] == [nil,nil,[]]) -def r; return [[]]; end; a,b,*c = r(); test_ok([a,b,c] == [[],nil,[]]) -def r; return [1,2]; end; a,b,*c = r(); test_ok([a,b,c] == [1,2,[]]) -def r; return [*[]]; end; a,b,*c = r(); test_ok([a,b,c] == [nil,nil,[]]) -def r; return [*[1]]; end; a,b,*c = r(); test_ok([a,b,c] == [1,nil,[]]) -def r; return [*[1,2]]; end; a,b,*c = r(); test_ok([a,b,c] == [1,2,[]]) - -def r; return *[]; end; a,b,*c = r(); test_ok([a,b,c] == [nil,nil,[]]) -def r; return *[1]; end; a,b,*c = r(); test_ok([a,b,c] == [1,nil,[]]) -def r; return *[nil]; end; a,b,*c = r(); test_ok([a,b,c] == [nil,nil,[]]) -def r; return *[[]]; end; a,b,*c = r(); test_ok([a,b,c] == [[],nil,[]]) -def r; return *[1,2]; end; a,b,*c = r(); test_ok([a,b,c] == [1,2,[]]) -def r; return *[*[]]; end; a,b,*c = r(); test_ok([a,b,c] == [nil,nil,[]]) -def r; return *[*[1]]; end; a,b,*c = r(); test_ok([a,b,c] == [1,nil,[]]) -def r; return *[*[1,2]]; end; a,b,*c = r(); test_ok([a,b,c] == [1,2,[]]) - -f = lambda {|r,| test_ok([] == r)} -f.call([], *[]) - -f = lambda {|r,*l| test_ok([] == r); test_ok([1] == l)} -f.call([], *[1]) - -f = lambda{|x| x} -test_ok(f.call(42) == 42) -test_ok(f.call([42]) == [42]) -test_ok(f.call([[42]]) == [[42]]) -test_ok(f.call([42,55]) == [42,55]) - -f = lambda{|x,| x} -test_ok(f.call(42) == 42) -test_ok(f.call([42]) == [42]) -test_ok(f.call([[42]]) == [[42]]) -test_ok(f.call([42,55]) == [42,55]) - -f = lambda{|*x| x} -test_ok(f.call(42) == [42]) -test_ok(f.call([42]) == [[42]]) -test_ok(f.call([[42]]) == [[[42]]]) -test_ok(f.call([42,55]) == [[42,55]]) -test_ok(f.call(42,55) == [42,55]) - -f = lambda { |a, b=42, *c| [a,b,c] } -test_ok(f.call(1 ) == [1,42,[ ]] ) -test_ok(f.call(1,43 ) == [1,43,[ ]] ) -test_ok(f.call(1,43,44) == [1,43,[44]] ) - -f = lambda { |a, b=(a|16), *c, &block| [a,b,c,block&&block[]] } -test_ok(f.call(8 ) == [8,24,[ ],nil] ) -test_ok(f.call(8,43 ) == [8,43,[ ],nil] ) -test_ok(f.call(8,43,44) == [8,43,[44],nil] ) -test_ok(f.call(8 ){45} == [8,24,[ ],45 ] ) -test_ok(f.call(8,43 ){45} == [8,43,[ ],45 ] ) -test_ok(f.call(8,43,44){45} == [8,43,[44],45 ] ) - -f = lambda { |a, b=42, *c, d| [a,b,c,d] } -test_ok(f.call(1 ,99) == [1,42,[ ],99] ) -test_ok(f.call(1,43 ,99) == [1,43,[ ],99] ) -test_ok(f.call(1,43,44,99) == [1,43,[44],99] ) - -f = lambda { |a, b=(a|16), &block| [a,b,block&&block[]] } -test_ok(f.call(8 ) == [8,24,nil] ) -test_ok(f.call(8,43) == [8,43,nil] ) -test_ok(f.call(8,43) == [8,43,nil] ) -test_ok(f.call(8 ){45} == [8,24,45 ] ) -test_ok(f.call(8,43){45} == [8,43,45 ] ) -test_ok(f.call(8,43){45} == [8,43,45 ] ) - -f = lambda { |a, b=42, d| [a,b,d] } -test_ok(f.call(1 ,99) == [1,42,99] ) -test_ok(f.call(1,43,99) == [1,43,99] ) -test_ok(f.call(1,43,99) == [1,43,99] ) - -f = lambda { |b=42, *c, &block| [b,c,block&&block[]] } -test_ok(f.call( ) == [42,[ ],nil] ) -test_ok(f.call(43 ) == [43,[ ],nil] ) -test_ok(f.call(43,44) == [43,[44],nil] ) -test_ok(f.call( ){45} == [42,[ ],45 ] ) -test_ok(f.call(43 ){45} == [43,[ ],45 ] ) -test_ok(f.call(43,44){45} == [43,[44],45 ] ) - -f = lambda { |b=42, *c, d| [b,c,d] } -test_ok(f.call( 99) == [42,[ ],99] ) -test_ok(f.call(43 ,99) == [43,[ ],99] ) -test_ok(f.call(43,44,99) == [43,[44],99] ) - -f = lambda { |b=42, &block| [b,block&&block[]] } -test_ok(f.call( ) == [42,nil] ) -test_ok(f.call(43) == [43,nil] ) -test_ok(f.call(43) == [43,nil] ) -test_ok(f.call( ){45} == [42,45 ] ) -test_ok(f.call(43){45} == [43,45 ] ) -test_ok(f.call(43){45} == [43,45 ] ) - -f = lambda { |b=42, d| [b,d] } -test_ok(f.call( 99) == [42,99] ) -test_ok(f.call(43,99) == [43,99] ) -test_ok(f.call(43,99) == [43,99] ) - - -a,=*[1] -test_ok(a == 1) -a,=*[[1]] -test_ok(a == [1]) -a,=*[[[1]]] -test_ok(a == [[1]]) - -x, (y, z) = 1, 2, 3 -test_ok([1,2,nil] == [x,y,z]) -x, (y, z) = 1, [2,3] -test_ok([1,2,3] == [x,y,z]) -x, (y, z) = 1, [2] -test_ok([1,2,nil] == [x,y,z]) - -a = loop do break; end; test_ok(a == nil) -a = loop do break nil; end; test_ok(a == nil) -a = loop do break 1; end; test_ok(a == 1) -a = loop do break []; end; test_ok(a == []) -a = loop do break [1]; end; test_ok(a == [1]) -a = loop do break [nil]; end; test_ok(a == [nil]) -a = loop do break [[]]; end; test_ok(a == [[]]) -a = loop do break [*[]]; end; test_ok(a == []) -a = loop do break [*[1]]; end; test_ok(a == [1]) -a = loop do break [*[1,2]]; end; test_ok(a == [1,2]) - -a = loop do break *[]; end; test_ok(a == []) -a = loop do break *[1]; end; test_ok(a == [1]) -a = loop do break *[nil]; end; test_ok(a == [nil]) -a = loop do break *[[]]; end; test_ok(a == [[]]) -a = loop do break *[*[]]; end; test_ok(a == []) -a = loop do break *[*[1]]; end; test_ok(a == [1]) -a = loop do break *[*[1,2]]; end; test_ok(a == [1,2]) - -*a = loop do break; end; test_ok(a == [nil]) -*a = loop do break nil; end; test_ok(a == [nil]) -*a = loop do break 1; end; test_ok(a == [1]) -*a = loop do break []; end; test_ok(a == []) -*a = loop do break [1]; end; test_ok(a == [1]) -*a = loop do break [nil]; end; test_ok(a == [nil]) -*a = loop do break [[]]; end; test_ok(a == [[]]) -*a = loop do break [1,2]; end; test_ok(a == [1,2]) -*a = loop do break [*[]]; end; test_ok(a == []) -*a = loop do break [*[1]]; end; test_ok(a == [1]) -*a = loop do break [*[1,2]]; end; test_ok(a == [1,2]) - -*a = loop do break *[]; end; test_ok(a == []) -*a = loop do break *[1]; end; test_ok(a == [1]) -*a = loop do break *[nil]; end; test_ok(a == [nil]) -*a = loop do break *[[]]; end; test_ok(a == [[]]) -*a = loop do break *[1,2]; end; test_ok(a == [1,2]) -*a = loop do break *[*[]]; end; test_ok(a == []) -*a = loop do break *[*[1]]; end; test_ok(a == [1]) -*a = loop do break *[*[1,2]]; end; test_ok(a == [1,2]) - -*a = *loop do break *[[]]; end; test_ok(a == [[]]) -*a = *loop do break *[1,2]; end; test_ok(a == [1,2]) -*a = *loop do break *[*[1,2]]; end; test_ok(a == [1,2]) - -a,b,*c = loop do break; end; test_ok([a,b,c] == [nil,nil,[]]) -a,b,*c = loop do break nil; end; test_ok([a,b,c] == [nil,nil,[]]) -a,b,*c = loop do break 1; end; test_ok([a,b,c] == [1,nil,[]]) -a,b,*c = loop do break []; end; test_ok([a,b,c] == [nil,nil,[]]) -a,b,*c = loop do break [1]; end; test_ok([a,b,c] == [1,nil,[]]) -a,b,*c = loop do break [nil]; end; test_ok([a,b,c] == [nil,nil,[]]) -a,b,*c = loop do break [[]]; end; test_ok([a,b,c] == [[],nil,[]]) -a,b,*c = loop do break [1,2]; end; test_ok([a,b,c] == [1,2,[]]) -a,b,*c = loop do break [*[]]; end; test_ok([a,b,c] == [nil,nil,[]]) -a,b,*c = loop do break [*[1]]; end; test_ok([a,b,c] == [1,nil,[]]) -a,b,*c = loop do break [*[1,2]]; end; test_ok([a,b,c] == [1,2,[]]) - -a,b,*c = loop do break *[]; end; test_ok([a,b,c] == [nil,nil,[]]) -a,b,*c = loop do break *[1]; end; test_ok([a,b,c] == [1,nil,[]]) -a,b,*c = loop do break *[nil]; end; test_ok([a,b,c] == [nil,nil,[]]) -a,b,*c = loop do break *[[]]; end; test_ok([a,b,c] == [[],nil,[]]) -a,b,*c = loop do break *[1,2]; end; test_ok([a,b,c] == [1,2,[]]) -a,b,*c = loop do break *[*[]]; end; test_ok([a,b,c] == [nil,nil,[]]) -a,b,*c = loop do break *[*[1]]; end; test_ok([a,b,c] == [1,nil,[]]) -a,b,*c = loop do break *[*[1,2]]; end; test_ok([a,b,c] == [1,2,[]]) - -def r(val); a = yield(); test_ok(a == val, 2); end -r(nil){next} -r(nil){next nil} -r(1){next 1} -r([]){next []} -r([1]){next [1]} -r([nil]){next [nil]} -r([[]]){next [[]]} -r([]){next [*[]]} -r([1]){next [*[1]]} -r([1,2]){next [*[1,2]]} - -r([]){next *[]} -r([1]){next *[1]} -r([nil]){next *[nil]} -r([[]]){next *[[]]} -r([]){next *[*[]]} -r([1]){next *[*[1]]} -r([1,2]){next *[*[1,2]]} - -def r(val); *a = yield(); test_ok(a == val, 2); end -r([nil]){next} -r([nil]){next nil} -r([1]){next 1} -r([]){next []} -r([1]){next [1]} -r([nil]){next [nil]} -r([[]]){next [[]]} -r([1,2]){next [1,2]} -r([]){next [*[]]} -r([1]){next [*[1]]} -r([1,2]){next [*[1,2]]} - -def r(val); *a = *yield(); test_ok(a == val, 2); end -r([[]]){next *[[]]} -r([1,2]){next *[1,2]} -r([1,2]){next *[*[1,2]]} - -def r(val); a,b,*c = yield(); test_ok([a,b,c] == val, 2); end -r([nil,nil,[]]){next} -r([nil,nil,[]]){next nil} -r([1,nil,[]]){next 1} -r([nil,nil,[]]){next []} -r([1,nil,[]]){next [1]} -r([nil,nil,[]]){next [nil]} -r([[],nil,[]]){next [[]]} -r([1,2,[]]){next [1,2]} -r([nil,nil,[]]){next [*[]]} -r([1,nil,[]]){next [*[1]]} -r([1,2,[]]){next [*[1,2]]} - -def r(val); a,b,*c = *yield(); test_ok([a,b,c] == val, 2); end -r([[],nil,[]]){next *[[]]} -r([1,2,[]]){next *[1,2]} -r([1,2,[]]){next *[*[1,2]]} - -test_check "condition" - -$x = '0'; - -$x == $x && test_ok(true) -$x != $x && test_ok(false) -$x == $x || test_ok(false) -$x != $x || test_ok(true) - -# first test to see if we can run the tests. - -test_check "if/unless"; - -$x = 'test'; -test_ok(if $x == $x then true else false end) -$bad = false -unless $x == $x - $bad = true -end -test_ok(!$bad) -test_ok(unless $x != $x then true else false end) - -test_check "case" - -case 5 -when 1, 2, 3, 4, 6, 7, 8 - test_ok(false) -when 5 - test_ok(true) -end - -case 5 -when 5 - test_ok(true) -when 1..10 - test_ok(false) -end - -case 5 -when 1..10 - test_ok(true) -else - test_ok(false) -end - -case 5 -when 5 - test_ok(true) -else - test_ok(false) -end - -case "foobar" -when /^f.*r$/ - test_ok(true) -else - test_ok(false) -end - -test_check "while/until"; - -while_tmp = "while_tmp.#{$$}" -tmp = open(while_tmp, "w") -tmp.print "tvi925\n"; -tmp.print "tvi920\n"; -tmp.print "vt100\n"; -tmp.print "Amiga\n"; -tmp.print "paper\n"; -tmp.close - -# test break - -tmp = open(while_tmp, "r") -test_ok(tmp.kind_of?(File)) - -while line = tmp.gets() - break if /vt100/ =~ line -end - -test_ok(!tmp.eof? && /vt100/ =~ line) -tmp.close - -# test next -$bad = false -tmp = open(while_tmp, "r") -while line = tmp.gets() - next if /vt100/ =~ line - $bad = 1 if /vt100/ =~ line -end -test_ok(!(!tmp.eof? || /vt100/ =~ line || $bad)) -tmp.close - -# test redo -$bad = false -tmp = open(while_tmp, "r") -while line = tmp.gets() - lastline = line - line = line.gsub(/vt100/, 'VT100') - if lastline != line - line.gsub!('VT100', 'Vt100') - redo - end - $bad = 1 if /vt100/ =~ line - $bad = 1 if /VT100/ =~ line -end -test_ok(tmp.eof? && !$bad) -tmp.close - -sum=0 -for i in 1..10 - sum += i - i -= 1 - if i > 0 - redo - end -end -test_ok(sum == 220) - -# test interval -$bad = false -tmp = open(while_tmp, "r") -while line = tmp.gets() - break if 3 - case line - when /vt100/, /Amiga/, /paper/ - $bad = true - end -end -test_ok(!$bad) -tmp.close - -File.unlink while_tmp or `/bin/rm -f "#{while_tmp}"` -test_ok(!File.exist?(while_tmp)) - -i = 0 -until i>4 - i+=1 -end -test_ok(i>4) - - -# exception handling -test_check "exception"; - -begin - raise "this must be handled" - test_ok(false) -rescue - test_ok(true) -end - -$bad = true -begin - raise "this must be handled no.2" -rescue - if $bad - $bad = false - retry - test_ok(false) - end -end -test_ok(true) - -# exception in rescue clause -$string = "this must be handled no.3" -begin - begin - raise "exception in rescue clause" - rescue - raise $string - end - test_ok(false) -rescue => e - test_ok($! == e) - test_ok(e.message == $string) - test_ok(e != $string) -end - -# exception in ensure clause -begin - begin - raise "this must be handled no.4" - ensure - raise "exception in ensure clause" - end - test_ok(false) -rescue - test_ok(true) -end - -$bad = true -begin - begin - raise "this must be handled no.5" - ensure - $bad = false - end -rescue -end -test_ok(!$bad) - -$bad = true -begin - begin - raise "this must be handled no.6" - ensure - $bad = false - end -rescue -end -test_ok(!$bad) - -$bad = true -while true - begin - break - ensure - $bad = false - end -end -test_ok(!$bad) - -test_ok(catch(:foo) { - loop do - loop do - throw :foo, true - break - end - break - test_ok(false) # should not reach here - end - false - }) - -test_check "array" -test_ok([1, 2] + [3, 4] == [1, 2, 3, 4]) -test_ok([1, 2] * 2 == [1, 2, 1, 2]) -test_ok([1, 2] * ":" == "1:2") - -test_ok([1, 2].hash == [1, 2].hash) - -test_ok([1,2,3] & [2,3,4] == [2,3]) -test_ok([1,2,3] | [2,3,4] == [1,2,3,4]) -test_ok([1,2,3] - [2,3] == [1]) - -$x = [0, 1, 2, 3, 4, 5] -test_ok($x[2] == 2) -test_ok($x[1..3] == [1, 2, 3]) -test_ok($x[1,3] == [1, 2, 3]) - -$x[0, 2] = 10 -test_ok($x[0] == 10 && $x[1] == 2) - -$x[0, 0] = -1 -test_ok($x[0] == -1 && $x[1] == 10) - -$x[-1, 1] = 20 -test_ok($x[-1] == 20 && $x.pop == 20) - -# array and/or -test_ok(([1,2,3]&[2,4,6]) == [2]) -test_ok(([1,2,3]|[2,4,6]) == [1,2,3,4,6]) - -# compact -$x = [nil, 1, nil, nil, 5, nil, nil] -$x.compact! -test_ok($x == [1, 5]) - -# uniq -$x = [1, 1, 4, 2, 5, 4, 5, 1, 2] -$x.uniq! -test_ok($x == [1, 4, 2, 5]) - -# empty? -test_ok(!$x.empty?) -$x = [] -test_ok($x.empty?) - -# sort -$x = ["it", "came", "to", "pass", "that", "..."] -$x = $x.sort.join(" ") -test_ok($x == "... came it pass that to") -$x = [2,5,3,1,7] -$x.sort!{|a,b| a<=>b} # sort with condition -test_ok($x == [1,2,3,5,7]) -$x.sort!{|a,b| b-a} # reverse sort -test_ok($x == [7,5,3,2,1]) - -# split test -$x = "The Book of Mormon" -test_ok($x.split(//).reverse!.join == $x.reverse) -test_ok($x.reverse == $x.reverse!) -test_ok("1 byte string".split(//).reverse.join(":") == "g:n:i:r:t:s: :e:t:y:b: :1") -$x = "a b c d" -test_ok($x.split == ['a', 'b', 'c', 'd']) -test_ok($x.split(' ') == ['a', 'b', 'c', 'd']) -test_ok(defined? "a".chomp) -test_ok("abc".scan(/./) == ["a", "b", "c"]) -test_ok("1a2b3c".scan(/(\d.)/) == [["1a"], ["2b"], ["3c"]]) -# non-greedy match -test_ok("a=12;b=22".scan(/(.*?)=(\d*);?/) == [["a", "12"], ["b", "22"]]) - -$x = [1] -test_ok(($x * 5).join(":") == '1:1:1:1:1') -test_ok(($x * 1).join(":") == '1') -test_ok(($x * 0).join(":") == '') - -*$x = *(1..7).to_a -test_ok($x.size == 7) -test_ok($x == [1, 2, 3, 4, 5, 6, 7]) - -$x = [1,2,3] -$x[1,0] = $x -test_ok($x == [1,1,2,3,2,3]) - -$x = [1,2,3] -$x[-1,0] = $x -test_ok($x == [1,2,1,2,3,3]) - -$x = [1,2,3] -$x.concat($x) -test_ok($x == [1,2,3,1,2,3]) - -test_check "hash" -$x = {1=>2, 2=>4, 3=>6} - -test_ok($x[1] == 2) - -test_ok(begin - for k,v in $x - raise if k*2 != v - end - true - rescue - false - end) - -test_ok($x.length == 3) -test_ok($x.has_key?(1)) -test_ok($x.has_value?(4)) -test_ok($x.values_at(2,3) == [4,6]) -test_ok($x == {1=>2, 2=>4, 3=>6}) - -$z = $x.keys.sort.join(":") -test_ok($z == "1:2:3") - -$z = $x.values.sort.join(":") -test_ok($z == "2:4:6") -test_ok($x == $x) - -$x.shift -test_ok($x.length == 2) - -$z = [1,2] -$x[$z] = 256 -test_ok($x[$z] == 256) - -$x = Hash.new(0) -$x[1] = 1 -test_ok($x[1] == 1) -test_ok($x[2] == 0) - -$x = Hash.new([]) -test_ok($x[22] == []) -test_ok($x[22].equal?($x[22])) - -$x = Hash.new{[]} -test_ok($x[22] == []) -test_ok(!$x[22].equal?($x[22])) - -$x = Hash.new{|h,k| $z = k; h[k] = k*2} -$z = 0 -test_ok($x[22] == 44) -test_ok($z == 22) -$z = 0 -test_ok($x[22] == 44) -test_ok($z == 0) -$x.default = 5 -test_ok($x[23] == 5) - -$x = Hash.new -def $x.default(k) - $z = k - self[k] = k*2 -end -$z = 0 -test_ok($x[22] == 44) -test_ok($z == 22) -$z = 0 -test_ok($x[22] == 44) -test_ok($z == 0) - -test_check "iterator" - -test_ok(!iterator?) - -def ttt - test_ok(iterator?) -end -ttt{} - -# yield at top level -test_ok(!defined?(yield)) - -$x = [1, 2, 3, 4] -$y = [] - -# iterator over array -for i in $x - $y.push i -end -test_ok($x == $y) - -# nested iterator -def tt - 1.upto(10) {|i| - yield i - } -end - -i=0 -tt{|i| break if i == 5} -test_ok(i == 0) - -def tt2(dummy) - yield 1 -end - -def tt3(&block) - tt2(raise(ArgumentError,""),&block) -end - -$x = false -begin - tt3{} -rescue ArgumentError - $x = true -rescue Exception -end -test_ok($x) - -def tt4 &block - tt2(raise(ArgumentError,""),&block) -end -$x = false -begin - tt4{} -rescue ArgumentError - $x = true -rescue Exception -end -test_ok($x) - -# iterator break/redo/next/retry -done = true -loop{ - break - done = false # should not reach here -} -test_ok(done) - -done = false -$bad = false -loop { - break if done - done = true - next - $bad = true # should not reach here -} -test_ok(!$bad) - -done = false -$bad = false -loop { - break if done - done = true - redo - $bad = true # should not reach here -} -test_ok(!$bad) - -$x = [] -for i in 1 .. 7 - $x.push i -end -test_ok($x.size == 7) -test_ok($x == [1, 2, 3, 4, 5, 6, 7]) - -# append method to built-in class -class Array - def iter_test1 - collect{|e| [e, yield(e)]}.sort{|a,b|a[1]<=>b[1]} - end - def iter_test2 - a = collect{|e| [e, yield(e)]} - a.sort{|a,b|a[1]<=>b[1]} - end -end -$x = [[1,2],[3,4],[5,6]] -test_ok($x.iter_test1{|x|x} == $x.iter_test2{|x|x}) - -class IterTest - def initialize(e); @body = e; end - - def each0(&block); @body.each(&block); end - def each1(&block); @body.each {|*x| block.call(*x) } end - def each2(&block); @body.each {|*x| block.call(x) } end - def each3(&block); @body.each {|x| block.call(*x) } end - def each4(&block); @body.each {|x| block.call(x) } end - def each5; @body.each {|*x| yield(*x) } end - def each6; @body.each {|*x| yield(x) } end - def each7; @body.each {|x| yield(*x) } end - def each8; @body.each {|x| yield(x) } end - - def f(a) - a - end -end -test_ok(IterTest.new(nil).method(:f).to_proc.call([1]) == [1]) -m = /\w+/.match("abc") -test_ok(IterTest.new(nil).method(:f).to_proc.call([m]) == [m]) - -IterTest.new([0]).each0 {|x| test_ok(x == 0)} -IterTest.new([1]).each1 {|x| test_ok(x == 1)} -IterTest.new([2]).each2 {|x| test_ok(x == [2])} -#IterTest.new([3]).each3 {|x| test_ok(x == 3)} -IterTest.new([4]).each4 {|x| test_ok(x == 4)} -IterTest.new([5]).each5 {|x| test_ok(x == 5)} -IterTest.new([6]).each6 {|x| test_ok(x == [6])} -#IterTest.new([7]).each7 {|x| test_ok(x == 7)} -IterTest.new([8]).each8 {|x| test_ok(x == 8)} - -IterTest.new([[0]]).each0 {|x| test_ok(x == [0])} -IterTest.new([[1]]).each1 {|x| test_ok(x == [1])} -IterTest.new([[2]]).each2 {|x| test_ok(x == [[2]])} -IterTest.new([[3]]).each3 {|x| test_ok(x == 3)} -IterTest.new([[4]]).each4 {|x| test_ok(x == [4])} -IterTest.new([[5]]).each5 {|x| test_ok(x == [5])} -IterTest.new([[6]]).each6 {|x| test_ok(x == [[6]])} -IterTest.new([[7]]).each7 {|x| test_ok(x == 7)} -IterTest.new([[8]]).each8 {|x| test_ok(x == [8])} - -IterTest.new([[0,0]]).each0 {|*x| test_ok(x == [[0,0]])} -IterTest.new([[8,8]]).each8 {|*x| test_ok(x == [[8,8]])} - -def m0(v) - v -end - -def m1 - m0(block_given?) -end -test_ok(m1{p 'test'}) -test_ok(!m1) - -def m - m0(block_given?,&Proc.new{}) -end -test_ok(m1{p 'test'}) -test_ok(!m1) - -class C - include Enumerable - def initialize - @a = [1,2,3] - end - def each(&block) - @a.each(&block) - end -end - -test_ok(C.new.collect{|n| n} == [1,2,3]) - -test_ok(Proc == lambda{}.class) -test_ok(Proc == Proc.new{}.class) -lambda{|a|test_ok(a==1)}.call(1) -def block_test(klass, &block) - test_ok(klass === block) -end - -block_test(NilClass) -block_test(Proc){} - -def call_argument_test(state, proc, *args) - x = state - begin - proc.call(*args) - rescue ArgumentError - x = !x - end - test_ok(x,2) -end - -call_argument_test(true, lambda{||}) -call_argument_test(false, lambda{||}, 1) -call_argument_test(true, lambda{|a,|}, 1) -call_argument_test(false, lambda{|a,|}) -call_argument_test(false, lambda{|a,|}, 1,2) - -call_argument_test(true, Proc.new{||}) -call_argument_test(true, Proc.new{||}, 1) -call_argument_test(true, Proc.new{|a,|}, 1) -call_argument_test(true, Proc.new{|a,|}) -call_argument_test(true, Proc.new{|a,|}, 1,2) - -def block_get(&block) - block -end - -test_ok(Proc == block_get{}.class) -call_argument_test(true, block_get{||}) -call_argument_test(true, block_get{||}, 1) -call_argument_test(true, block_get{|a,|}, 1) -call_argument_test(true, block_get{|a,|}) -call_argument_test(true, block_get{|a,|}, 1,2) - -call_argument_test(true, block_get(&lambda{||})) -call_argument_test(false, block_get(&lambda{||}),1) -call_argument_test(true, block_get(&lambda{|a,|}),1) -call_argument_test(false, block_get(&lambda{|a,|}),1,2) - -blk = block_get{11} -test_ok(blk.class == Proc) -test_ok(blk.to_proc.class == Proc) -test_ok(blk.clone.call == 11) -test_ok(block_get(&blk).class == Proc) - -lmd = lambda{44} -test_ok(lmd.class == Proc) -test_ok(lmd.to_proc.class == Proc) -test_ok(lmd.clone.call == 44) -test_ok(block_get(&lmd).class == Proc) - -test_ok(Proc.new{|a,| a}.yield(1,2,3) == 1) -call_argument_test(true, Proc.new{|a,|}, 1,2) - -test_ok(Proc.new{|&b| b.call(10)}.call {|x| x} == 10) -test_ok(Proc.new{|a,&b| b.call(a)}.call(12) {|x| x} == 12) - -def test_return1 - Proc.new { - return 55 - }.yield + 5 -end -test_ok(test_return1() == 55) -def test_return2 - lambda { - return 55 - }.call + 5 -end -test_ok(test_return2() == 60) - -def proc_call(&b) - b.call -end -def proc_yield() - yield -end -def proc_return1 - lambda{return 42}.call+1 -end -test_ok(proc_return1() == 43) -def proc_return2 - ->{return 42}.call+1 -end -test_ok(proc_return2() == 43) -def proc_return3 - proc_call{return 42}+1 -end -test_ok(proc_return3() == 42) -def proc_return4 - proc_yield{return 42}+1 -end -test_ok(proc_return4() == 42) - -def ljump_test(state, proc, *args) - x = state - begin - proc.call(*args) - rescue LocalJumpError - x = !x - end - test_ok(x,2) -end - -ljump_test(false, block_get{break}) -ljump_test(true, lambda{break}) - -def exit_value_test(&block) - block.call -rescue LocalJumpError - $!.exit_value -end - -test_ok(45 == exit_value_test{break 45}) - -test_ok(55 == begin - block_get{break 55}.call - rescue LocalJumpError - $!.exit_value - end) - -def block_call(&block) - block.call -end - -def test_b1 - block_call{break 11} -end -test_ok(test_b1() == 11) - -def ljump_rescue(r) - begin - yield - rescue LocalJumpError => e - r if /from proc-closure/ =~ e.message - end -end - -def test_b2 - ljump_rescue(22) do - block_get{break 21}.call - end -end -test_ok(test_b2() == 22) - -def test_b3 - ljump_rescue(33) do - Proc.new{break 31}.yield - end -end -test_ok(test_b3() == 33) - -def test_b4 - lambda{break 44}.call -end -test_ok(test_b4() == 44) - -def test_b5 - ljump_rescue(55) do - b = block_get{break 54} - block_call(&b) - end -end -test_ok(test_b5() == 55) - -def test_b6 - b = lambda{break 67} - block_call(&b) - 66 -end -test_ok(test_b6() == 66) - -def util_r7 - block_get{break 78} -end - -def test_b7 - b = util_r7() - ljump_rescue(77) do - block_call(&b) - end -end -test_ok(test_b7() == 77) - -def util_b8(&block) - block_call(&block) -end - -def test_b8 - util_b8{break 88} -end -test_ok(test_b8() == 88) - -def util_b9(&block) - lambda{block.call; 98}.call -end - -def test_b9 - util_b9{break 99} -end -test_ok(test_b9() == 99) - -def util_b10 - util_b9{break 100} -end - -def test_b10 - util_b10() -end -test_ok(test_b10() == 100) - -def test_b11 - ljump_rescue(111) do - loop do - Proc.new{break 110}.yield - break 112 - end - end -end -test_ok(test_b11() == 111) - -def test_b12 - loop do - break lambda{break 122}.call - break 121 - end -end -test_ok(test_b12() == 122) - -def test_b13 - ljump_rescue(133) do - while true - Proc.new{break 130}.yield - break 131 - end - end -end -test_ok(test_b13() == 133) - -def test_b14 - while true - break lambda{break 144}.call - break 143 - end -end -test_ok(test_b14() == 144) - -def test_b15 - [0].each {|c| yield 1 } - 156 -end -test_ok(test_b15{|e| break 155 } == 155) - -def marity_test(m) - method = method(m) - test_ok(method.arity == method.to_proc.arity, 2) -end -marity_test(:test_ok) -marity_test(:marity_test) -marity_test(:p) - -lambda(&method(:test_ok)).call(true) -lambda(&block_get{|a,n| test_ok(a,n)}).call(true, 2) - -class ITER_TEST1 - def a - block_given? - end -end - -class ITER_TEST2 < ITER_TEST1 - def a - test_ok(super) - super - end -end -test_ok(ITER_TEST2.new.a {}) - -class ITER_TEST3 - def foo x - return yield if block_given? - x - end -end - -class ITER_TEST4 < ITER_TEST3 - def foo x - test_ok(super == yield) - test_ok(super(x, &nil) == x) - end -end - -ITER_TEST4.new.foo(44){55} - -class ITER_TEST5 - def tt(aa) - aa - end - - def uu(a) - class << self - define_method(:tt) do |sym| - super(sym) - end - end - end - - def xx(*x) - x.size - end -end - -a = ITER_TEST5.new -a.uu(12) -test_ok(a.tt(1) == 1) - -class ITER_TEST6 < ITER_TEST5 - def xx(*a) - a << 12 - super - end -end - -test_ok(ITER_TEST6.new.xx([24]) == 2) - -test_check "float" -test_ok(2.6.floor == 2) -test_ok((-2.6).floor == -3) -test_ok(2.6.ceil == 3) -test_ok((-2.6).ceil == -2) -test_ok(2.6.truncate == 2) -test_ok((-2.6).truncate == -2) -test_ok(2.6.round == 3) -test_ok((-2.4).truncate == -2) -test_ok((13.4 % 1 - 0.4).abs < 0.0001) -nan = 0.0/0 -def nan_test(x,y) - test_ok(x != y) - test_ok((x < y) == false) - test_ok((x > y) == false) - test_ok((x <= y) == false) - test_ok((x >= y) == false) -end -nan_test(nan, nan) -nan_test(nan, 0) -nan_test(nan, 1) -nan_test(nan, -1) -nan_test(nan, 1000) -nan_test(nan, -1000) -nan_test(nan, 1_000_000_000_000) -nan_test(nan, -1_000_000_000_000) -nan_test(nan, 100.0); -nan_test(nan, -100.0); -nan_test(nan, 0.001); -nan_test(nan, -0.001); -nan_test(nan, 1.0/0); -nan_test(nan, -1.0/0); - -#s = "3.7517675036461267e+17" -#test_ok(s == sprintf("%.16e", s.to_f)) -f = 3.7517675036461267e+17 -test_ok(f == sprintf("%.16e", f).to_f) - - -test_check "bignum" -def fact(n) - return 1 if n == 0 - f = 1 - while n>0 - f *= n - n -= 1 - end - return f -end -$x = fact(40) -test_ok($x == $x) -test_ok($x == fact(40)) -test_ok($x < $x+2) -test_ok($x > $x-2) -test_ok($x == 815915283247897734345611269596115894272000000000) -test_ok($x != 815915283247897734345611269596115894272000000001) -test_ok($x+1 == 815915283247897734345611269596115894272000000001) -test_ok($x/fact(20) == 335367096786357081410764800000) -$x = -$x -test_ok($x == -815915283247897734345611269596115894272000000000) -test_ok(2-(2**32) == -(2**32-2)) -test_ok(2**32 - 5 == (2**32-3)-2) - -$good = true; -for i in 1000..1014 - $good = false if ((1 << i) != (2**i)) -end -test_ok($good) - -$good = true; -n1= 1 << 1000 -for i in 1000..1014 - $good = false if ((1 << i) != n1) - n1 *= 2 -end -test_ok($good) - -$good = true; -n2=n1 -for i in 1..10 - n1 = n1 / 2 - n2 = n2 >> 1 - $good = false if (n1 != n2) -end -test_ok($good) - -$good = true; -for i in 4000..4096 - n1 = 1 << i; - if (n1**2-1) / (n1+1) != (n1-1) - $good = false - end -end -test_ok($good) - -b = 10**80 -a = b * 9 + 7 -test_ok(7 == a.modulo(b)) -test_ok(-b + 7 == a.modulo(-b)) -test_ok(b + -7 == (-a).modulo(b)) -test_ok(-7 == (-a).modulo(-b)) -test_ok(7 == a.remainder(b)) -test_ok(7 == a.remainder(-b)) -test_ok(-7 == (-a).remainder(b)) -test_ok(-7 == (-a).remainder(-b)) - -test_ok(10**40+10**20 == 10000000000000000000100000000000000000000) -test_ok(10**40/10**20 == 100000000000000000000) - -a = 677330545177305025495135714080 -b = 14269972710765292560 -test_ok(a % b == 0) -test_ok(-a % b == 0) - -def shift_test(a) - b = a / (2 ** 32) - c = a >> 32 - test_ok(b == c) - - b = a * (2 ** 32) - c = a << 32 - test_ok(b == c) -end - -shift_test(-4518325415524767873) -shift_test(-0xfffffffffffffffff) - -test_check "string & char" - -test_ok("abcd" == "abcd") -test_ok("abcd" =~ /abcd/) -test_ok("abcd" === "abcd") -# compile time string concatenation -test_ok("ab" "cd" == "abcd") -test_ok("#{22}aa" "cd#{44}" == "22aacd44") -test_ok("#{22}aa" "cd#{44}" "55" "#{66}" == "22aacd445566") -test_ok("abc" !~ /^$/) -test_ok("abc\n" !~ /^$/) -test_ok("abc" !~ /^d*$/) -test_ok(("abc" =~ /d*$/) == 3) -test_ok("" =~ /^$/) -test_ok("\n" =~ /^$/) -test_ok("a\n\n" =~ /^$/) -test_ok("abcabc" =~ /.*a/ && $& == "abca") -test_ok("abcabc" =~ /.*c/ && $& == "abcabc") -test_ok("abcabc" =~ /.*?a/ && $& == "a") -test_ok("abcabc" =~ /.*?c/ && $& == "abc") -test_ok(/(.|\n)*?\n(b|\n)/ =~ "a\nb\n\n" && $& == "a\nb") - -test_ok(/^(ab+)+b/ =~ "ababb" && $& == "ababb") -test_ok(/^(?:ab+)+b/ =~ "ababb" && $& == "ababb") -test_ok(/^(ab+)+/ =~ "ababb" && $& == "ababb") -test_ok(/^(?:ab+)+/ =~ "ababb" && $& == "ababb") - -test_ok(/(\s+\d+){2}/ =~ " 1 2" && $& == " 1 2") -test_ok(/(?:\s+\d+){2}/ =~ " 1 2" && $& == " 1 2") - -$x = <') == "") - -# character constants(assumes ASCII) -test_ok("a"[0] == ?a) -test_ok(?a == ?a) -test_ok(?\C-a == "\1") -test_ok(?\M-a == "\341") -test_ok(?\M-\C-a == "\201") -test_ok("a".upcase![0] == ?A) -test_ok("A".downcase![0] == ?a) -test_ok("abc".tr!("a-z", "A-Z") == "ABC") -test_ok("aabbcccc".tr_s!("a-z", "A-Z") == "ABC") -test_ok("abcc".squeeze!("a-z") == "abc") -test_ok("abcd".delete!("bc") == "ad") - -$x = "abcdef" -$y = [ ?a, ?b, ?c, ?d, ?e, ?f ] -$bad = false -$x.each_byte {|i| - if i.chr != $y.shift - $bad = true - break - end -} -test_ok(!$bad) - -s = "a string" -s[0..s.size]="another string" -test_ok(s == "another string") - -s = < Object) == -1) -test_ok((Object <=> String) == 1) -test_ok((Array <=> String) == nil) - -test_check "clone" -foo = Object.new -def foo.test - "test" -end -bar = foo.clone -def bar.test2 - "test2" -end - -test_ok(bar.test2 == "test2") -test_ok(bar.test == "test") -test_ok(foo.test == "test") - -begin - foo.test2 - test_ok false -rescue NoMethodError - test_ok true -end - -module M001; end -module M002; end -module M003; include M002; end -module M002; include M001; end -module M003; include M002; end - -test_ok(M003.ancestors == [M003, M002, M001]) - -test_check "marshal" -$x = [1,2,3,[4,5,"foo"],{1=>"bar"},2.5,fact(30)] -$y = Marshal.dump($x) -test_ok($x == Marshal.load($y)) - -StrClone=String.clone; -test_ok(Marshal.load(Marshal.dump(StrClone.new("abc"))).class == StrClone) - -[[1,2,3,4], [81, 2, 118, 3146]].each { |w,x,y,z| - a = (x.to_f + y.to_f / z.to_f) * Math.exp(w.to_f / (x.to_f + y.to_f / z.to_f)) - ma = Marshal.dump(a) - b = Marshal.load(ma) - test_ok(a == b) -} - -test_check "pack" - -$format = "c2x5CCxsdils_l_a6"; -# Need the expression in here to force ary[5] to be numeric. This avoids -# test2 failing because ary2 goes str->numeric->str and ary does not. -ary = [1,-100,127,128,32767,987.654321098 / 100.0,12345,123456,-32767,-123456,"abcdef"] -$x = ary.pack($format) -ary2 = $x.unpack($format) - -test_ok(ary.length == ary2.length) -test_ok(ary.join(':') == ary2.join(':')) -test_ok($x =~ /def/) - -$x = [-1073741825] -test_ok($x.pack("q").unpack("q") == $x) - -test_check "math" -test_ok(Math.sqrt(4) == 2) - -include Math -test_ok(sqrt(4) == 2) - -test_check "struct" -struct_test = Struct.new("Test", :foo, :bar) -test_ok(struct_test == Struct::Test) - -test = struct_test.new(1, 2) -test_ok(test.foo == 1 && test.bar == 2) -test_ok(test[0] == 1 && test[1] == 2) - -a, b = test.to_a -test_ok(a == 1 && b == 2) - -test[0] = 22 -test_ok(test.foo == 22) - -test.bar = 47 -test_ok(test.bar == 47) - -test_check "variable" -test_ok($$.instance_of?(Integer)) - -# read-only variable -begin - $$ = 5 - test_ok false -rescue NameError - test_ok true -end - -foobar = "foobar" -$_ = foobar -test_ok($_ == foobar) - -class Gods - @@rule = "Uranus" # private to Gods - def ruler0 - @@rule - end - - def self.ruler1 # <= per method definition style - @@rule - end - class << self # <= multiple method definition style - def ruler2 - @@rule - end - end -end - -module Olympians - @@rule ="Zeus" - def ruler3 - @@rule - end -end - -class Titans < Gods - @@rule = "Cronus" # do not affect @@rule in Gods - include Olympians - def ruler4 - @@rule - end -end - -test_ok(Gods.new.ruler0 == "Cronus") -test_ok(Gods.ruler1 == "Cronus") -test_ok(Gods.ruler2 == "Cronus") -test_ok(Titans.ruler1 == "Cronus") -test_ok(Titans.ruler2 == "Cronus") -atlas = Titans.new -test_ok(atlas.ruler0 == "Cronus") -test_ok(atlas.ruler3 == "Zeus") -test_ok(atlas.ruler4 == "Cronus") - -test_check "trace" -$x = 1234 -$y = 0 -trace_var :$x, Proc.new{$y = $x} -$x = 40414 -test_ok($y == $x) - -untrace_var :$x -$x = 19660208 -test_ok($y != $x) - -trace_var :$x, Proc.new{$x *= 2} -$x = 5 -test_ok($x == 10) - -untrace_var :$x - -test_check "defined?" - -test_ok(defined?($x)) # global variable -test_ok(defined?($x) == 'global-variable')# returns description - -foo=5 -test_ok(defined?(foo)) # local variable - -test_ok(defined?(Array)) # constant -test_ok(defined?(Object.new)) # method -test_ok(!defined?(Object.print))# private method -test_ok(defined?(1 == 2)) # operator expression - -class Foo - def foo - p :foo - end - protected :foo - def bar(f) - test_ok(defined?(self.foo)) - test_ok(defined?(f.foo)) - end -end -f = Foo.new -test_ok(defined?(f.foo) == nil) -f.bar(f) - -def defined_test - return !defined?(yield) -end - -test_ok(defined_test) # not iterator -test_ok(!defined_test{}) # called as iterator - -test_check "alias" -class Alias0 - def foo; "foo" end -end -class Alias1 < Alias0 - alias bar foo - def foo; "foo+" + super end -end -class Alias2 < Alias1 - alias baz foo - undef foo -end - -x = Alias2.new -test_ok(x.bar == "foo") -test_ok(x.baz == "foo+foo") - -# test_check for cache -test_ok(x.baz == "foo+foo") - -class Alias3 < Alias2 - def foo - defined? super - end - def bar - defined? super - end - def quux - defined? super - end -end -x = Alias3.new -test_ok(!x.foo) -test_ok(x.bar) -test_ok(!x.quux) - -test_check "path" -test_ok(File.basename("a") == "a") -test_ok(File.basename("a/b") == "b") -test_ok(File.basename("a/b/") == "b") -test_ok(File.basename("/") == "/") -test_ok(File.basename("//") == "/") -test_ok(File.basename("///") == "/") -test_ok(File.basename("a/b////") == "b") -test_ok(File.basename("a.rb", ".rb") == "a") -test_ok(File.basename("a.rb///", ".rb") == "a") -test_ok(File.basename("a.rb///", ".*") == "a") -test_ok(File.basename("a.rb///", ".c") == "a.rb") -test_ok(File.dirname("a") == ".") -test_ok(File.dirname("/") == "/") -test_ok(File.dirname("/a") == "/") -test_ok(File.dirname("a/b") == "a") -test_ok(File.dirname("a/b/c") == "a/b") -test_ok(File.dirname("/a/b/c") == "/a/b") -test_ok(File.dirname("/a/b/") == "/a") -test_ok(File.dirname("/a/b///") == "/a") -case Dir.pwd -when %r'\A\w:' - test_ok(/\A\w:\/\z/ =~ File.expand_path(".", "/")) - test_ok(/\A\w:\/a\z/ =~ File.expand_path("a", "/")) - dosish = true -when %r'\A//' - test_ok(%r'\A//[^/]+/[^/]+\z' =~ File.expand_path(".", "/")) - test_ok(%r'\A//[^/]+/[^/]+/a\z' =~ File.expand_path(".", "/")) - dosish = true -else - test_ok(File.expand_path(".", "/") == "/") - test_ok(File.expand_path("sub", "/") == "/sub") -end -if dosish - test_ok(File.expand_path("/", "//machine/share/sub") == "//machine/share") - test_ok(File.expand_path("/dir", "//machine/share/sub") == "//machine/share/dir") - test_ok(File.expand_path("/", "z:/sub") == "z:/") - test_ok(File.expand_path("/dir", "z:/sub") == "z:/dir") -end -test_ok(File.expand_path(".", "//") == "//") -test_ok(File.expand_path("sub", "//") == "//sub") - -# test_check "Proc#binding" -ObjectSpace.each_object(Proc){|o| - begin - b = o.binding - eval 'self', b - rescue ArgumentError - end -} - -test_check "gc" -begin - 1.upto(10000) { - tmp = [0,1,2,3,4,5,6,7,8,9] - } - tmp = nil - test_ok true -rescue - test_ok false -end -class S - def initialize(a) - @a = a - end -end -l=nil -100000.times { - l = S.new(l) -} -GC.start -test_ok true # reach here or dumps core -l = [] -100000.times { - l.push([l]) -} -GC.start -test_ok true # reach here or dumps core - -ObjectSpace.each_object{|o| - o.class.name -} - -test_ok true # reach here or dumps core - -PROGRESS.finish -if $failed > 0 - printf "not ok/test: %d failed %d\n", $ntest, $failed -else - printf "end of test(test: %d)\n", $ntest -end diff --git a/src/main/antlr4/depends/extractor/ruby/test/throwcatch.rb b/src/main/antlr4/depends/extractor/ruby/test/throwcatch.rb deleted file mode 100644 index 40fad98..0000000 --- a/src/main/antlr4/depends/extractor/ruby/test/throwcatch.rb +++ /dev/null @@ -1,15 +0,0 @@ -def promptAndGet(prompt) - print prompt - res = readline.chomp - throw :quitRequested if res == "!" - return res -end - -catch :quitRequested do - name = promptAndGet("Name: ") - age = promptAndGet("Age: ") - sex = promptAndGet("Sex: ") - # .. - # 处理信息 -end -promptAndGet("Name:") diff --git a/src/main/antlr4/depends/extractor/ruby/test/truncked.rb b/src/main/antlr4/depends/extractor/ruby/test/truncked.rb deleted file mode 100644 index d920c72..0000000 --- a/src/main/antlr4/depends/extractor/ruby/test/truncked.rb +++ /dev/null @@ -1,11 +0,0 @@ -def self.on_signal name, action # :nodoc: - supported = SIGNALS[name] - - old_trap = trap name do - old_trap.call if old_trap.respond_to? :call - action.call - end if supported - yield - ensure - trap name, old_trap if supported -end diff --git a/src/main/antlr4/depends/extractor/ruby/test/unless.rb b/src/main/antlr4/depends/extractor/ruby/test/unless.rb deleted file mode 100644 index a3a1945..0000000 --- a/src/main/antlr4/depends/extractor/ruby/test/unless.rb +++ /dev/null @@ -1,6 +0,0 @@ - unless options[:seed] then - srand - options[:seed] = (ENV["SEED"] || srand).to_i % 0xFFFF - orig_args << "--seed" << options[:seed].to_s - end - diff --git a/src/main/antlr4/depends/extractor/ruby/test/when.rb b/src/main/antlr4/depends/extractor/ruby/test/when.rb deleted file mode 100644 index 3689ae9..0000000 --- a/src/main/antlr4/depends/extractor/ruby/test/when.rb +++ /dev/null @@ -1,6 +0,0 @@ -def validate_recursive(expected_schema, datum, path, result) - case expected_schema.type_sym - when :null - fail TypeMismatchError unless datum.nil? - end -end diff --git a/src/main/antlr4/depends/extractor/ruby/test/when_statement.rb b/src/main/antlr4/depends/extractor/ruby/test/when_statement.rb deleted file mode 100644 index 37e62b5..0000000 --- a/src/main/antlr4/depends/extractor/ruby/test/when_statement.rb +++ /dev/null @@ -1,13 +0,0 @@ -$age = 5 -case $age -when 0 .. 2 - puts "婴儿" -when 3 .. 6 - puts "小孩" -when 7 .. 12 - puts "child" -when 13 .. 18 - puts "少年" -else - puts "其他年龄段的" -end diff --git a/src/main/antlr4/depends/extractor/ruby/test_all.sh b/src/main/antlr4/depends/extractor/ruby/test_all.sh deleted file mode 100755 index 0c5675a..0000000 --- a/src/main/antlr4/depends/extractor/ruby/test_all.sh +++ /dev/null @@ -1,4 +0,0 @@ -for FILE in `ls *.rb` -do -echo $FILE; ./test.sh $FILE -done diff --git a/src/main/antlr4/depends/extractor/ruby/test_all_in_computer.sh b/src/main/antlr4/depends/extractor/ruby/test_all_in_computer.sh deleted file mode 100755 index 5523d8d..0000000 --- a/src/main/antlr4/depends/extractor/ruby/test_all_in_computer.sh +++ /dev/null @@ -1,5 +0,0 @@ -for FILE in `cat filelist.txt` -do -echo $FILE -./test.sh $FILE -done diff --git a/src/main/antlr4/depends/extractor/ruby/tokentest.sh b/src/main/antlr4/depends/extractor/ruby/tokentest.sh deleted file mode 100755 index 30104e7..0000000 --- a/src/main/antlr4/depends/extractor/ruby/tokentest.sh +++ /dev/null @@ -1,11 +0,0 @@ -rm *.java -rm *.class - -export CLASSPATH=.:/usr/share/java/stringtemplate4.jar:/usr/share/java/antlr4.jar:/usr/share/java/antlr4-runtime.jar:/usr/share/java/antlr3-runtime.jar/:/usr/share/java/treelayout.jar - -antlr4 RubyLexer.g4 -antlr4 RubyParser.g4 - -javac -cp $CLASSPATH *.java - -exec java -cp $CLASSPATH org.antlr.v4.gui.TestRig Ruby prog -tokens $1 diff --git a/src/main/antlr4/depends/extractor/ruby/tree.sh b/src/main/antlr4/depends/extractor/ruby/tree.sh deleted file mode 100755 index cbd6bc7..0000000 --- a/src/main/antlr4/depends/extractor/ruby/tree.sh +++ /dev/null @@ -1,3 +0,0 @@ -export CLASSPATH=.:/usr/share/java/stringtemplate4.jar:/usr/share/java/antlr4.jar:/usr/share/java/antlr4-runtime.jar:/usr/share/java/antlr3-runtime.jar/:/usr/share/java/treelayout.jar - -exec java -cp $CLASSPATH org.antlr.v4.gui.TestRig Ruby prog $1 -tree -gui diff --git a/src/main/java/depends/entity/ContainerEntity.java b/src/main/java/depends/entity/ContainerEntity.java index 8578d90..3f50718 100644 --- a/src/main/java/depends/entity/ContainerEntity.java +++ b/src/main/java/depends/entity/ContainerEntity.java @@ -21,12 +21,15 @@ public abstract class ContainerEntity extends DecoratedEntity { private ArrayList vars; private ArrayList functions; private HashMap expressions; - + private Collection mixins; + private Collection resolvedMixins; public ContainerEntity(String rawName, Entity parent, Integer id) { super(rawName, parent, id); vars = new ArrayList<>(); functions = new ArrayList<>(); + mixins = new ArrayList<>(); + resolvedMixins = new ArrayList<>(); expressions = new HashMap<>(); } @@ -73,6 +76,20 @@ public abstract class ContainerEntity extends DecoratedEntity { for (FunctionEntity func:this.functions) { func.inferLocalLevelEntities(inferer); } + resolvedMixins = identiferToContainerEntity(inferer, mixins); + } + + private Collection identiferToContainerEntity(Inferer inferer, Collection identifiers) { + ArrayList r = new ArrayList<>(); + for (String identifier : identifiers) { + Entity entity = inferer.resolveName(this, identifier, true); + if (entity==null) { + continue; + } + if (entity instanceof ContainerEntity) + r.add((ContainerEntity)entity); + } + return r; } /** @@ -182,4 +199,10 @@ public abstract class ContainerEntity extends DecoratedEntity { } return null; } + + + + public void addMixin(String moduleName) { + mixins.add(moduleName); + } } diff --git a/src/main/java/depends/entity/VarEntity.java b/src/main/java/depends/entity/VarEntity.java index 56ea33e..fd47e0a 100644 --- a/src/main/java/depends/entity/VarEntity.java +++ b/src/main/java/depends/entity/VarEntity.java @@ -1,12 +1,8 @@ package depends.entity; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; - import depends.relations.Inferer; -public class VarEntity extends DecoratedEntity { +public class VarEntity extends ContainerEntity { private String rawType; private TypeEntity type; diff --git a/src/main/java/depends/extractor/HandlerContext.java b/src/main/java/depends/extractor/HandlerContext.java index 55ae711..3828ca6 100644 --- a/src/main/java/depends/extractor/HandlerContext.java +++ b/src/main/java/depends/extractor/HandlerContext.java @@ -138,10 +138,15 @@ public abstract class HandlerContext { public void foundExtends(String typeName) { if (currentType()==null) { System.out.println("error: type do not exist"); + return ; } currentType().addExtends(typeName); } + public void foundMixin(String moduleName) { + lastContainer().addMixin(moduleName); + + } public void foundTypeParametes(String typeName) { lastContainer().addTypeParameter(typeName); diff --git a/src/main/java/depends/extractor/cpp/cdt/CdtCppEntitiesListener.java b/src/main/java/depends/extractor/cpp/cdt/CdtCppEntitiesListener.java index d3eed0a..da129fb 100644 --- a/src/main/java/depends/extractor/cpp/cdt/CdtCppEntitiesListener.java +++ b/src/main/java/depends/extractor/cpp/cdt/CdtCppEntitiesListener.java @@ -55,9 +55,6 @@ public class CdtCppEntitiesListener extends ASTVisitor { @Override public int visit(IASTTranslationUnit tu) { - if (context.currentFile().getRawName().contains("ItfmEqptRegistration.cpp")) { - System.out.println("hh"); - } for (String incl:preprocessorHandler.getDirectIncludedFiles(tu.getAllPreprocessorStatements())) { context.foundNewImport(new FileImport(incl)); CdtCppFileParser importedParser = new CdtCppFileParser(incl, entityRepo, preprocessorHandler,inferer); diff --git a/src/main/java/depends/extractor/ruby/IncludedFileLocator.java b/src/main/java/depends/extractor/ruby/IncludedFileLocator.java new file mode 100644 index 0000000..c86a786 --- /dev/null +++ b/src/main/java/depends/extractor/ruby/IncludedFileLocator.java @@ -0,0 +1,24 @@ +package depends.extractor.ruby; + +import java.io.File; +import java.util.List; + +import depends.util.FileUtil; + +public class IncludedFileLocator { + private List includesPath; + public IncludedFileLocator(List includedPath) { + this.includesPath = includedPath; + } + public String uniqFileName(String startLocation, String importedFilename) { + if (FileUtil.existFile(importedFilename)) return FileUtil.uniqFilePath(importedFilename); + String dirPath = FileUtil.getLocatedDir(startLocation); + String path = dirPath + File.separator + importedFilename; + if (FileUtil.existFile(path)) return FileUtil.uniqFilePath(path); + for (String includePath:includesPath) { + path = includePath + File.separator + importedFilename; + if (FileUtil.existFile(path)) return FileUtil.uniqFilePath(path); + } + return null; + } +} diff --git a/src/main/java/depends/extractor/ruby/RubyFileParser.java b/src/main/java/depends/extractor/ruby/RubyFileParser.java index aec4f1c..e9f62c3 100644 --- a/src/main/java/depends/extractor/ruby/RubyFileParser.java +++ b/src/main/java/depends/extractor/ruby/RubyFileParser.java @@ -21,16 +21,19 @@ import org.antlr.v4.runtime.tree.ParseTreeWalker; import depends.entity.repo.EntityRepo; import depends.extractor.FileParser; +import depends.util.FileUtil; public class RubyFileParser implements FileParser { - private static final long MAX_PARSE_TIME_PER_FILE = 30000L; + private static final long MAX_PARSE_TIME_PER_FILE = 180000L; private String fileFullPath; private EntityRepo entityRepo; private ExecutorService executor; + private IncludedFileLocator includesFileLocator; - public RubyFileParser(String fileFullPath, EntityRepo entityRepo, ExecutorService executorService) { - this.fileFullPath = fileFullPath; + public RubyFileParser(String fileFullPath, EntityRepo entityRepo, ExecutorService executorService, IncludedFileLocator includesFileLocator) { + this.fileFullPath = FileUtil.uniqFilePath(fileFullPath); this.entityRepo = entityRepo; this.executor = executorService; + this.includesFileLocator = includesFileLocator; } @Override @@ -42,7 +45,7 @@ public class RubyFileParser implements FileParser { @Override public RuleContext call() throws Exception { RubyParser parser = new RubyParser(tokens); - return parser.prog(); + return parser.compilation_unit(); } /* The following function is try to optimize performance with SLL mode, but @@ -54,7 +57,7 @@ public class RubyFileParser implements FileParser { parser.setErrorHandler(new BailErrorStrategy()); parser.getInterpreter().setPredictionMode(PredictionMode.SLL); try { - return parser.prog(); + return parser.compilation_unit(); } catch (final ParseCancellationException e) { // fall-back to LL mode parsing if SLL fails @@ -63,7 +66,7 @@ public class RubyFileParser implements FileParser { parser.removeErrorListeners(); parser.setErrorHandler(new DefaultErrorStrategy()); parser.getInterpreter().setPredictionMode(PredictionMode.LL); - return parser.prog(); + return parser.compilation_unit(); } } }); @@ -80,7 +83,7 @@ public class RubyFileParser implements FileParser { System.err.println("parse error in " + fileFullPath); return; } - RubyListener bridge = new RubyListener(fileFullPath, entityRepo); + RubyListener bridge = new RubyListener(fileFullPath, entityRepo, includesFileLocator); ParseTreeWalker walker = new ParseTreeWalker(); walker.walk(bridge, rootContext); } diff --git a/src/main/java/depends/extractor/ruby/RubyHandlerContext.java b/src/main/java/depends/extractor/ruby/RubyHandlerContext.java new file mode 100644 index 0000000..da8acf1 --- /dev/null +++ b/src/main/java/depends/extractor/ruby/RubyHandlerContext.java @@ -0,0 +1,64 @@ +package depends.extractor.ruby; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +import depends.entity.Entity; +import depends.entity.PackageEntity; +import depends.entity.repo.EntityRepo; +import depends.extractor.HandlerContext; +import depends.extractor.ruby.RubyParser.Function_call_paramContext; +import depends.extractor.ruby.RubyParser.PrimaryFunctionCall0Context; +import depends.importtypes.FileImport; +import depends.importtypes.Import; + +public class RubyHandlerContext extends HandlerContext { + + public RubyHandlerContext(EntityRepo entityRepo) { + super(entityRepo); + } + + public Entity foundNamespace(String nampespaceName) { + PackageEntity pkgEntity = new PackageEntity(nampespaceName, currentFile(),idGenerator.generateId()); + entityRepo.add(pkgEntity); + entityStack.push(pkgEntity); + return pkgEntity; + } + + public void processSpecialFuncCall(String methodName, Collection params, IncludedFileLocator includedFileLocator) { + // Handle Import relation + if(methodName.equals("require") || methodName.equals("require_relative")) { + for (String importedFilename:params) { + if (!importedFilename.endsWith(".rb")) importedFilename = importedFilename + ".rb"; + String inclFileName = includedFileLocator.uniqFileName(currentFile().getRawName(),importedFilename); + if (inclFileName==null) { + System.err.println("cannot found included file" + inclFileName); + continue; + } + foundNewImport(new FileImport(inclFileName)); + } + } + // Handle Extend relation + else if (methodName.equals("extend")) { + for (String parentName:params) { + foundExtends(parentName); + } + } + // Handle mixin relation + else if (methodName.equals("include")) { + for (String moduleName:params) { + foundMixin(moduleName); + } + } + // attribute methods + else if (methodName.equals("attr_accessor")||methodName.equals("attr_writer")||methodName.equals("attr_reader")) { + for (String name:params) { + name = name.replace(":", ""); //remove symbol + foundMethodDeclarator(name, null, new ArrayList<>()); + } + } + } + + +} diff --git a/src/main/java/depends/extractor/ruby/RubyImportLookupStrategy.java b/src/main/java/depends/extractor/ruby/RubyImportLookupStrategy.java index 93617e0..787240f 100644 --- a/src/main/java/depends/extractor/ruby/RubyImportLookupStrategy.java +++ b/src/main/java/depends/extractor/ruby/RubyImportLookupStrategy.java @@ -1,10 +1,12 @@ package depends.extractor.ruby; +import java.util.ArrayList; import java.util.List; import depends.entity.Entity; import depends.entity.FileEntity; import depends.entity.repo.EntityRepo; +import depends.importtypes.FileImport; import depends.importtypes.Import; import depends.relations.ImportLookupStrategy; import depends.relations.Inferer; @@ -18,21 +20,27 @@ public class RubyImportLookupStrategy implements ImportLookupStrategy { } @Override - public List getImportedRelationEntities(List importedNames, EntityRepo repo) { - // TODO Auto-generated method stub - return null; + public List getImportedRelationEntities(List importedList, EntityRepo repo) { + ArrayList result = new ArrayList<>(); + for (Import importedItem:importedList) { + if (importedItem instanceof FileImport) { + Entity imported = repo.getEntity(importedItem.getContent()); + if (imported==null) continue; + result.add(imported); + } + } + return result; } @Override public List getImportedTypes(List importedNames, EntityRepo repo) { // TODO Auto-generated method stub - return null; + return new ArrayList<>(); } @Override - public List getImportedFiles(List importedNames, EntityRepo repo) { - // TODO Auto-generated method stub - return null; + public List getImportedFiles(List importedList, EntityRepo repo) { + return getImportedRelationEntities(importedList,repo); } } diff --git a/src/main/java/depends/extractor/ruby/RubyListener.java b/src/main/java/depends/extractor/ruby/RubyListener.java index f6a6335..6476912 100644 --- a/src/main/java/depends/extractor/ruby/RubyListener.java +++ b/src/main/java/depends/extractor/ruby/RubyListener.java @@ -1,9 +1,173 @@ package depends.extractor.ruby; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +import depends.entity.Expression; +import depends.entity.VarEntity; import depends.entity.repo.EntityRepo; +import depends.extractor.ruby.RubyParser.Alias_statementContext; +import depends.extractor.ruby.RubyParser.Class_definitionContext; +import depends.extractor.ruby.RubyParser.ExprAssignContext; +import depends.extractor.ruby.RubyParser.ExprBatchAssignContext; +import depends.extractor.ruby.RubyParser.ExprFunctionCall1Context; +import depends.extractor.ruby.RubyParser.ExprFunctionCall2Context; +import depends.extractor.ruby.RubyParser.ExprFunctionCall3Context; +import depends.extractor.ruby.RubyParser.Function_call_paramContext; +import depends.extractor.ruby.RubyParser.Function_definitionContext; +import depends.extractor.ruby.RubyParser.Function_definition_paramContext; +import depends.extractor.ruby.RubyParser.Module_definitionContext; +import depends.extractor.ruby.RubyParser.PrimaryFunctionCall0Context; +import depends.extractor.ruby.RubyParser.PrimaryStatementRaiseContext; +import depends.extractor.ruby.RubyParser.PrimaryStatementReturnContext; +import depends.extractor.ruby.RubyParser.PrimaryStatementYieldContext; +import depends.extractor.ruby.RubyParser.Undef_statementContext; +import depends.importtypes.FileImport; +import depends.util.FileUtil; public class RubyListener extends RubyParserBaseListener{ - public RubyListener(String fileFullPath, EntityRepo entityRepo) { + private RubyHandlerContext context; + private EntityRepo entityRepo; + private IncludedFileLocator includedFileLocator; + RubyParserHelper helper = new RubyParserHelper(); + + public RubyListener(String fileFullPath, EntityRepo entityRepo,IncludedFileLocator includedFileLocator) { + this.context = new RubyHandlerContext(entityRepo); + this.entityRepo = entityRepo; + this.includedFileLocator = includedFileLocator; + context.startFile(fileFullPath); + } + + + //Alias + @Override + public void enterAlias_statement(Alias_statementContext ctx) { + context.foundNewTypeAlias(helper.getName(ctx.function_name_or_symbol(0)), helper.getName(ctx.function_name_or_symbol(1))); + super.enterAlias_statement(ctx); + } + + //Undef + @Override + public void enterUndef_statement(Undef_statementContext ctx) { + // TODO Auto-generated method stub + super.enterUndef_statement(ctx); + } + + //Module + @Override + public void enterModule_definition(Module_definitionContext ctx) { + context.foundNamespace(helper.getName(ctx)); + super.enterModule_definition(ctx); + } + @Override + public void exitModule_definition(Module_definitionContext ctx) { + context.exitLastedEntity(); + super.exitModule_definition(ctx); + } + + + //Class + @Override + public void enterClass_definition(Class_definitionContext ctx) { + if (helper.isSingletonClass(ctx)) { + //TODO: lookup the name of variable, and add method to it + String varName = helper.getName(ctx); + }else { + context.foundNewType(helper.getName(ctx)); + } + super.enterClass_definition(ctx); + } + @Override + public void exitClass_definition(Class_definitionContext ctx) { + if (helper.isSingletonClass(ctx)) { + //TODO: lookup the name of variable, and gracefully exit it + String varName = helper.getName(ctx); + }else { + context.exitLastedEntity(); + } + super.exitClass_definition(ctx); + } + + //Function + @Override + public void enterFunction_definition(Function_definitionContext ctx) { + context.foundMethodDeclarator(helper.getName(ctx), null, new ArrayList<>()); + if (ctx.function_definition_header().function_definition_params()!=null) { + for ( Function_definition_paramContext param:ctx.function_definition_header().function_definition_params().function_definition_param()) { + VarEntity var = new VarEntity(helper.getName(param), null, context.currentFunction(), entityRepo.generateId()); + context.currentFunction().addParameter(var); + } + } + super.enterFunction_definition(ctx); + } + + + @Override + public void exitFunction_definition(Function_definitionContext ctx) { + context.exitLastedEntity(); + super.exitFunction_definition(ctx); + } + + //Assign + @Override + public void enterExprBatchAssign(ExprBatchAssignContext ctx) { + // TODO Auto-generated method stub + super.enterExprBatchAssign(ctx); + } + @Override + public void enterExprAssign(ExprAssignContext ctx) { + // TODO Auto-generated method stub + super.enterExprAssign(ctx); + } + + //Call + @Override + public void enterPrimaryFunctionCall0(PrimaryFunctionCall0Context ctx) { + String fname = this.helper.getName(ctx.function_name()); + List parameters = ctx.func_call_parameters().function_call_param(); + Collection params = helper.getAllArgName(ctx.func_call_parameters().function_call_param()); + context.processSpecialFuncCall(fname,params,includedFileLocator); + super.enterPrimaryFunctionCall0(ctx); + } + + @Override + public void enterExprFunctionCall1(ExprFunctionCall1Context ctx) { + String fname = this.helper.getName(ctx.function_name()); + + Collection params = helper.getAllArgName(ctx.func_call_parameters_no_bracket().function_call_param()); + context.processSpecialFuncCall(fname,params,includedFileLocator); + super.enterExprFunctionCall1(ctx); + } + @Override + public void enterExprFunctionCall2(ExprFunctionCall2Context ctx) { + // TODO Auto-generated method stub + super.enterExprFunctionCall2(ctx); + } + @Override + public void enterExprFunctionCall3(ExprFunctionCall3Context ctx) { + // TODO Auto-generated method stub + super.enterExprFunctionCall3(ctx); + } + //Yield(Call) + @Override + public void enterPrimaryStatementYield(PrimaryStatementYieldContext ctx) { + // TODO Auto-generated method stub + super.enterPrimaryStatementYield(ctx); + } + + //Return + @Override + public void enterPrimaryStatementReturn(PrimaryStatementReturnContext ctx) { + // TODO Auto-generated method stub + super.enterPrimaryStatementReturn(ctx); + } + + //Throw + @Override + public void enterPrimaryStatementRaise(PrimaryStatementRaiseContext ctx) { + // TODO Auto-generated method stub + super.enterPrimaryStatementRaise(ctx); } } diff --git a/src/main/java/depends/extractor/ruby/RubyParserHelper.java b/src/main/java/depends/extractor/ruby/RubyParserHelper.java new file mode 100644 index 0000000..777e47c --- /dev/null +++ b/src/main/java/depends/extractor/ruby/RubyParserHelper.java @@ -0,0 +1,145 @@ +package depends.extractor.ruby; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashSet; +import java.util.List; + +import depends.entity.VarEntity; +import depends.extractor.ruby.RubyParser.Class_definitionContext; +import depends.extractor.ruby.RubyParser.CpathContext; +import depends.extractor.ruby.RubyParser.ExprContext; +import depends.extractor.ruby.RubyParser.ExprPrimaryContext; +import depends.extractor.ruby.RubyParser.Func_call_parametersContext; +import depends.extractor.ruby.RubyParser.Func_call_parameters_no_bracketContext; +import depends.extractor.ruby.RubyParser.Function_call_paramContext; +import depends.extractor.ruby.RubyParser.Function_definitionContext; +import depends.extractor.ruby.RubyParser.Function_definition_paramContext; +import depends.extractor.ruby.RubyParser.Function_nameContext; +import depends.extractor.ruby.RubyParser.Function_name_or_symbolContext; +import depends.extractor.ruby.RubyParser.IdentifierContext; +import depends.extractor.ruby.RubyParser.Module_definitionContext; +import depends.extractor.ruby.RubyParser.PrimaryContext; +import depends.extractor.ruby.RubyParser.PrimarySymbolContext; +import depends.extractor.ruby.RubyParser.PrimaryVarPathContext; +import depends.extractor.ruby.RubyParser.SymbolContext; +import depends.extractor.ruby.RubyParser.Variable_pathContext; + +public class RubyParserHelper { + + public String getName(Function_name_or_symbolContext context) { + if (context.function_name()!=null) + return getName(context.function_name()); + if (context.symbol()!=null) + return getName(context.symbol()); + return null; + } + + public String getName(SymbolContext symbol) { + return getName(symbol.identifier()); + } + + public String getName(Function_nameContext function_name) { + if (function_name.cpath()!=null) return getName(function_name.cpath()); + return function_name.getText(); //+=.. operators + } + + public String getName(CpathContext cpath) { + StringBuilder sb = new StringBuilder(); + for (IdentifierContext id:cpath.identifier()) { + sb.append(getName(id)); + } + return sb.toString(); + } + + /** + * Return the actual name. It could include the prefix of scope including + * $(global) @@(class var) @(instance var) , $number/special, and also {} [] + * @param id + * @return + */ + public String getName(IdentifierContext id) { + return id.getText(); + } + + public String getName(Module_definitionContext ctx) { + return getName(ctx.cpath()); + } + + public String getName(Class_definitionContext ctx) { + if (ctx.class_header().cpath()!=null) return getName(ctx.class_header().cpath()); + return getName(ctx.class_header().identifier()); + } + + public boolean isSingletonClass(Class_definitionContext ctx) { + if (ctx.class_header().BIT_SHL()!=null) return true; + return false; + } + + public String getName(Function_definitionContext ctx) { + return getName(ctx.function_definition_header().function_name()); + } + + public String getName(Function_definition_paramContext param) { + if (param.identifier()!=null) return getName(param.identifier()); + return getName(param.hash_asso().expr().get(0)); + } + + private String getName(ExprContext exprContext) { + if (exprContext instanceof ExprPrimaryContext) { + ExprPrimaryContext ctx = (ExprPrimaryContext)exprContext; + return getName(ctx.primary()); + } + return ""; + } + + private String getName(PrimaryContext primary) { + if (primary instanceof PrimaryVarPathContext) { + return getName (((PrimaryVarPathContext)primary).variable_path()); + } + if (primary instanceof PrimarySymbolContext) { + return getName (((PrimarySymbolContext)primary).symbol()); + } + return ""; + } + + private String getName(Variable_pathContext variable_path) { + return variable_path.getText(); + } + + + public Collection getAllArgName(List func_call_parameters) { + Collection r = new HashSet<>(); + for (Function_call_paramContext param:func_call_parameters) { + extractNameFromExpr(r,param.expr()); + } + return r; + } + + private void extractNameFromExpr(Collection result, ExprContext exprContext) { + if (exprContext!=null) { + if (exprContext instanceof ExprPrimaryContext) { + ExprPrimaryContext c = (ExprPrimaryContext)(exprContext); + result.add(extractNameOfPrimary(c.primary())); + } + else { + System.err.println(exprContext.getClass().getSimpleName()); + } + } + } + + private String extractNameOfPrimary(PrimaryContext primary) { + if (primary instanceof PrimaryVarPathContext) { + PrimaryVarPathContext varPath = (PrimaryVarPathContext)primary; + return varPath.getText().replace("'", "").replace("\"", ""); + } + if (primary instanceof PrimarySymbolContext) { + PrimarySymbolContext symbol = (PrimarySymbolContext)primary; + return symbol.getText().replace(":","").replace("'", "").replace("\"", ""); + } + System.err.println(primary.getClass().getSimpleName()); + return null; + } + + +} diff --git a/src/main/java/depends/extractor/ruby/RubyWorker.java b/src/main/java/depends/extractor/ruby/RubyWorker.java index 31606db..aac357d 100644 --- a/src/main/java/depends/extractor/ruby/RubyWorker.java +++ b/src/main/java/depends/extractor/ruby/RubyWorker.java @@ -7,17 +7,16 @@ import java.util.concurrent.Executors; import depends.extractor.AbstractLangWorker; import depends.extractor.FileParser; -import depends.extractor.cpp.cdt.PreprocessorHandler; import depends.relations.Inferer; public class RubyWorker extends AbstractLangWorker { private static final String LANG = "ruby"; - private static final String[] SUFFIX = new String[] {".rb",".ruby"}; - PreprocessorHandler preprocessorHandler; + private static final String[] SUFFIX = new String[] {".rb"}; + IncludedFileLocator preprocessorHandler; private ExecutorService executor; public RubyWorker(String inputDir, String[] includeDir) { super(inputDir,includeDir); - preprocessorHandler = new PreprocessorHandler(super.includePaths()); + preprocessorHandler = new IncludedFileLocator(super.includePaths()); inferer = new Inferer(entityRepo,new RubyImportLookupStrategy(),new RubyBuiltInType()); executor = Executors.newSingleThreadExecutor(); } @@ -36,11 +35,11 @@ public class RubyWorker extends AbstractLangWorker { @Override protected FileParser getFileParser(String fileFullPath) { - return new RubyFileParser(fileFullPath,entityRepo,executor); + return new RubyFileParser(fileFullPath,entityRepo,executor,preprocessorHandler); } public List getErrors(){ - return new ArrayList(preprocessorHandler.getNotExistedIncludedFiles()); + return new ArrayList(); } diff --git a/src/main/java/depends/util/FileUtil.java b/src/main/java/depends/util/FileUtil.java index 0b081f3..6d5edb6 100644 --- a/src/main/java/depends/util/FileUtil.java +++ b/src/main/java/depends/util/FileUtil.java @@ -20,4 +20,10 @@ public class FileUtil { public static boolean isDirectory(String path) { return new File(path).isDirectory(); } + + public static String getLocatedDir(String filepath) { + File file = new File(filepath); + if (!file.exists()) return null; + return file.getParent(); + } } diff --git a/src/test/java/depends/extractor/ruby/RubyParserTest.java b/src/test/java/depends/extractor/ruby/RubyParserTest.java new file mode 100644 index 0000000..5661ce8 --- /dev/null +++ b/src/test/java/depends/extractor/ruby/RubyParserTest.java @@ -0,0 +1,28 @@ +package depends.extractor.ruby; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +import depends.entity.repo.EntityRepo; +import depends.relations.Inferer; + +public abstract class RubyParserTest { + protected EntityRepo entityRepo ; + protected Inferer inferer ; + + public void init() { + entityRepo = new EntityRepo(); + inferer = new Inferer(entityRepo,new RubyImportLookupStrategy(),new RubyBuiltInType()); + } + + public RubyFileParser createParser(String src) { + ExecutorService executor = Executors.newSingleThreadExecutor(); + return new RubyFileParser(src,entityRepo, executor,new IncludedFileLocator(includePaths())); + } + + private List includePaths() { + return new ArrayList<>(); + } +} diff --git a/src/test/java/depends/extractor/ruby/RubyRequireTest.java b/src/test/java/depends/extractor/ruby/RubyRequireTest.java new file mode 100644 index 0000000..eca29b8 --- /dev/null +++ b/src/test/java/depends/extractor/ruby/RubyRequireTest.java @@ -0,0 +1,31 @@ +package depends.extractor.ruby; + +import static org.junit.Assert.assertEquals; + +import java.io.File; +import java.io.IOException; + +import org.junit.Before; +import org.junit.Test; + +public class RubyRequireTest extends RubyParserTest { + @Before + public void setUp() { + super.init(); + } + @Test + public void test_require_relation() throws IOException { + String[] srcs = new String[] { + "./src/test/resources/ruby-code-examples/require_1.rb", + "./src/test/resources/ruby-code-examples/require_2.rb", + }; + + for (String src:srcs) { + RubyFileParser parser = createParser(src); + parser.parse(); + } + inferer.resolveAllBindings(); + File f = new File(srcs[0]); + assertEquals(1,entityRepo.getEntity(f.getCanonicalPath()).getRelations().size()); + } +} diff --git a/src/test/resources/ruby-code-examples/require_1.rb b/src/test/resources/ruby-code-examples/require_1.rb new file mode 100644 index 0000000..e7d5907 --- /dev/null +++ b/src/test/resources/ruby-code-examples/require_1.rb @@ -0,0 +1 @@ +require 'require_2' diff --git a/src/test/resources/ruby-code-examples/require_2.rb b/src/test/resources/ruby-code-examples/require_2.rb new file mode 100644 index 0000000..e7d5907 --- /dev/null +++ b/src/test/resources/ruby-code-examples/require_2.rb @@ -0,0 +1 @@ +require 'require_2'