├── .gitignore
├── README.md
├── docker-compose.yml
├── pom.xml
└── src
├── main
├── antlr4
│ └── evolution
│ │ └── analysis
│ │ ├── jv
│ │ ├── JavaLexer.g4
│ │ └── JavaParser.g4
│ │ └── sql
│ │ └── Sql.g4
├── docker
│ └── Dockerfile
├── java
│ └── evolution
│ │ ├── Main.java
│ │ ├── analysis
│ │ └── jv
│ │ │ ├── ParseClassApp.java
│ │ │ ├── ParseClassService.java
│ │ │ ├── ParsePackageService.java
│ │ │ ├── ProcessFiles.java
│ │ │ ├── calls
│ │ │ ├── JavaCallApp.java
│ │ │ ├── JavaCallVisitor.java
│ │ │ ├── JavaDaoParser.java
│ │ │ ├── JavaMethodCallStore.java
│ │ │ ├── model
│ │ │ │ └── JMethodCall.java
│ │ │ └── plugins
│ │ │ │ ├── JavaDaoStringParser.java
│ │ │ │ ├── MyBatisParser.java
│ │ │ │ └── sql
│ │ │ │ ├── TableOpParser.java
│ │ │ │ └── TableVisitor.java
│ │ │ └── identifier
│ │ │ ├── JIdentifier.java
│ │ │ ├── JMethod.java
│ │ │ ├── JavaClassQuery.java
│ │ │ ├── JavaFileParser.java
│ │ │ ├── JavaIdentifierApp.java
│ │ │ ├── JavaIdentifierStore.java
│ │ │ └── JavaIdentifierVisitor.java
│ │ ├── configuration
│ │ └── ConfigReader.java
│ │ ├── factory
│ │ ├── ServiceFactory.java
│ │ └── daoparser
│ │ │ ├── DaoParserProvider.java
│ │ │ ├── DaoParserTypeEnum.java
│ │ │ ├── JavaDaoParserFactory.java
│ │ │ └── OutOfJavaDaoParserEnumError.java
│ │ └── store
│ │ ├── HelloWorldExample.java
│ │ ├── Neo4JDriverFactory.java
│ │ └── StoreManager.java
└── resources
│ ├── application.yaml
│ └── logging.properties
└── test
└── java
└── evolution
├── ConfigReaderTest.java
├── MainTest.java
├── analysis
└── jv
│ └── calls
│ └── plugins
│ └── JavaCallVisitorTest.java
└── factory
└── daoparser
├── FakeConfigReader.java
└── JavaDaoParserFactoryTest.java
/.gitignore:
--------------------------------------------------------------------------------
1 | *.class
2 |
3 | # BlueJ files
4 | *.ctxt
5 |
6 | # Mobile Tools for Java (J2ME)
7 | .mtj.tmp/
8 |
9 | # Package Files #
10 | *.jar
11 | *.war
12 | *.ear
13 |
14 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
15 | hs_err_pid*
16 |
17 | # ANTLR4 and program generated files
18 | target/
19 |
20 | ParseClassClientDemo.java
21 | prod.yaml
22 |
23 | .settings
24 | .vscode
25 | bin
26 | .classpath
27 | .project
28 | *.iml
29 | *.ipr
30 | *.iws
31 | **/.DS_Store
32 |
33 | **/example/
34 | # Created by https://www.gitignore.io/api/intellij+all
35 |
36 | ### Intellij+all ###
37 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm
38 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
39 |
40 | # User-specific stuff
41 | .idea/**/workspace.xml
42 | .idea/**/tasks.xml
43 | .idea/**/usage.statistics.xml
44 | .idea/**/dictionaries
45 | .idea/**/shelf
46 |
47 | # Generated files
48 | .idea/**/contentModel.xml
49 |
50 | # Sensitive or high-churn files
51 | .idea/**/dataSources/
52 | .idea/**/dataSources.ids
53 | .idea/**/dataSources.local.xml
54 | .idea/**/sqlDataSources.xml
55 | .idea/**/dynamic.xml
56 | .idea/**/uiDesigner.xml
57 | .idea/**/dbnavigator.xml
58 |
59 | # Gradle
60 | .idea/**/gradle.xml
61 | .idea/**/libraries
62 |
63 | # Gradle and Maven with auto-import
64 | # When using Gradle or Maven with auto-import, you should exclude module files,
65 | # since they will be recreated, and may cause churn. Uncomment if using
66 | # auto-import.
67 | # .idea/modules.xml
68 | # .idea/*.iml
69 | # .idea/modules
70 |
71 | # CMake
72 | cmake-build-*/
73 |
74 | # Mongo Explorer plugin
75 | .idea/**/mongoSettings.xml
76 |
77 | # File-based project format
78 | *.iws
79 |
80 | # IntelliJ
81 | out/
82 |
83 | # mpeltonen/sbt-idea plugin
84 | .idea_modules/
85 |
86 | # JIRA plugin
87 | atlassian-ide-plugin.xml
88 |
89 | # Cursive Clojure plugin
90 | .idea/replstate.xml
91 |
92 | # Crashlytics plugin (for Android Studio and IntelliJ)
93 | com_crashlytics_export_strings.xml
94 | crashlytics.properties
95 | crashlytics-build.properties
96 | fabric.properties
97 |
98 | # Editor-based Rest Client
99 | .idea/httpRequests
100 |
101 | # Android studio 3.1+ serialized cache file
102 | .idea/caches/build_file_checksums.ser
103 |
104 | ### Intellij+all Patch ###
105 | # Ignores the whole .idea folder and all .iml files
106 | # See https://github.com/joeblau/gitignore.io/issues/186 and https://github.com/joeblau/gitignore.io/issues/360
107 |
108 | .idea/
109 |
110 | # Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-249601023
111 |
112 | *.iml
113 | modules.xml
114 | .idea/misc.xml
115 | *.ipr
116 |
117 |
118 | # End of https://www.gitignore.io/api/intellij+all
119 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Analysis Java Dependence
2 |
3 | #Setup analysis java server
4 | ```
5 | docker build -t analysis_java -f src/main/docker/Dockerfile .
6 | docker-compose up
7 | ```
8 |
9 | #Useage
10 | the server is running
11 | ```
12 | GET http://localhost:8080/greet/world
13 | ```
14 |
15 | analysis API
16 | ```
17 | POST http://localhost:8080/analysis/class/{class}
18 | POST http://localhost:8080/analysis/package/{package}
19 | ```
--------------------------------------------------------------------------------
/docker-compose.yml:
--------------------------------------------------------------------------------
1 | version: '3'
2 |
3 | networks:
4 | neo4j:
5 | driver: bridge
6 |
7 | services:
8 |
9 | analysis_java:
10 | image: analysis_java
11 | depends_on:
12 | - neo4j
13 | volumes: ## adds app folder to the container
14 | - /Users/xfwu/Workspace/petclinet/:/workspace
15 | networks: ## connects neo4j to app container
16 | - neo4j
17 | ports: ## publish ports
18 | - "8080:8080"
19 | working_dir: /app ## uses work dir /app
20 |
21 | neo4j:
22 | image: neo4j:3.4 ## we use neo4j v3
23 | ports: ## publish ports to have Web UI
24 | - "7474:7474"
25 | - "7687:7687"
26 | networks:
27 | - neo4j
28 | volumes: ## adds folder with login/password
29 | - $HOME/neo4j/data:/data
30 | #--env=NEO4J_dbms_memory_pagecache_size=2G --env=NEO4J_dbms_memory_heap_max__size=2G
31 |
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
3 | 4.0.0
4 |
5 | me.refactoring.analysis
6 | dependencies_java
7 | 1.0
8 | jar
9 |
10 | dependencies_java
11 | http://maven.apache.org
12 |
13 |
14 | UTF-8
15 | true
16 | true
17 |
18 |
19 |
20 |
21 |
22 | org.neo4j.driver
23 | neo4j-java-driver
24 | 1.4.4
25 |
26 |
27 |
28 | org.antlr
29 | antlr4-runtime
30 | 4.7
31 |
32 |
33 | io.helidon.webserver
34 | helidon-webserver-bundle
35 | 0.10.0
36 |
37 |
38 | io.helidon.config
39 | helidon-config-yaml
40 | 0.10.0
41 |
42 |
43 | org.junit.jupiter
44 | junit-jupiter-api
45 | 5.1.0
46 | test
47 |
48 |
49 | org.junit.jupiter
50 | junit-jupiter-engine
51 | 5.1.0
52 | test
53 |
54 |
55 | org.junit.platform
56 | junit-platform-surefire-provider
57 | 1.0.3
58 |
59 |
60 | org.hamcrest
61 | hamcrest-library
62 | 1.3
63 | test
64 |
65 |
66 |
67 |
68 |
69 |
70 | src/main/resources
71 |
72 |
73 |
74 |
75 |
76 | org.apache.maven.plugins
77 | maven-compiler-plugin
78 | 3.1
79 |
80 | 1.8
81 | 1.8
82 |
83 |
84 |
91 |
92 | org.antlr
93 | antlr4-maven-plugin
94 | 4.7
95 |
96 |
97 |
98 | antlr4
99 |
100 |
101 |
102 |
103 |
104 | org.apache.maven.plugins
105 | maven-resources-plugin
106 | 3.0.2
107 |
108 |
112 |
137 |
138 | org.apache.maven.plugins
139 | maven-dependency-plugin
140 |
141 |
142 | copy-dependencies
143 | prepare-package
144 |
145 | copy-dependencies
146 |
147 |
148 | ${project.build.directory}/libs
149 | false
150 | false
151 | true
152 | true
153 | runtime
154 | test
155 |
156 |
157 |
158 |
159 |
160 |
161 | org.apache.maven.plugins
162 | maven-jar-plugin
163 | 3.1.0
164 |
165 |
166 |
167 | true
168 | libs
169 | evolution.Main
170 |
171 |
172 |
173 |
174 |
175 | org.apache.maven.plugins
176 | maven-surefire-plugin
177 | 2.19.1
178 |
179 |
180 | org.junit.platform
181 | junit-platform-surefire-provider
182 | 1.1.0
183 |
184 |
185 |
186 |
187 |
188 |
--------------------------------------------------------------------------------
/src/main/antlr4/evolution/analysis/jv/JavaLexer.g4:
--------------------------------------------------------------------------------
1 | /*
2 | [The "BSD licence"]
3 | Copyright (c) 2013 Terence Parr, Sam Harwell
4 | Copyright (c) 2017 Ivan Kochurkin (upgrade to Java 8)
5 | All rights reserved.
6 |
7 | Redistribution and use in source and binary forms, with or without
8 | modification, are permitted provided that the following conditions
9 | are met:
10 | 1. Redistributions of source code must retain the above copyright
11 | notice, this list of conditions and the following disclaimer.
12 | 2. Redistributions in binary form must reproduce the above copyright
13 | notice, this list of conditions and the following disclaimer in the
14 | documentation and/or other materials provided with the distribution.
15 | 3. The name of the author may not be used to endorse or promote products
16 | derived from this software without specific prior written permission.
17 |
18 | THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 | IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 | OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 | IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 | NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 | THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 | */
29 |
30 | lexer grammar JavaLexer;
31 |
32 | // Keywords
33 |
34 | ABSTRACT: 'abstract';
35 | ASSERT: 'assert';
36 | BOOLEAN: 'boolean';
37 | BREAK: 'break';
38 | BYTE: 'byte';
39 | CASE: 'case';
40 | CATCH: 'catch';
41 | CHAR: 'char';
42 | CLASS: 'class';
43 | CONST: 'const';
44 | CONTINUE: 'continue';
45 | DEFAULT: 'default';
46 | DO: 'do';
47 | DOUBLE: 'double';
48 | ELSE: 'else';
49 | ENUM: 'enum';
50 | EXTENDS: 'extends';
51 | FINAL: 'final';
52 | FINALLY: 'finally';
53 | FLOAT: 'float';
54 | FOR: 'for';
55 | IF: 'if';
56 | GOTO: 'goto';
57 | IMPLEMENTS: 'implements';
58 | IMPORT: 'import';
59 | INSTANCEOF: 'instanceof';
60 | INT: 'int';
61 | INTERFACE: 'interface';
62 | LONG: 'long';
63 | NATIVE: 'native';
64 | NEW: 'new';
65 | PACKAGE: 'package';
66 | PRIVATE: 'private';
67 | PROTECTED: 'protected';
68 | PUBLIC: 'public';
69 | RETURN: 'return';
70 | SHORT: 'short';
71 | STATIC: 'static';
72 | STRICTFP: 'strictfp';
73 | SUPER: 'super';
74 | SWITCH: 'switch';
75 | SYNCHRONIZED: 'synchronized';
76 | THIS: 'this';
77 | THROW: 'throw';
78 | THROWS: 'throws';
79 | TRANSIENT: 'transient';
80 | TRY: 'try';
81 | VOID: 'void';
82 | VOLATILE: 'volatile';
83 | WHILE: 'while';
84 |
85 | // Literals
86 |
87 | DECIMAL_LITERAL: ('0' | [1-9] (Digits? | '_'+ Digits)) [lL]?;
88 | HEX_LITERAL: '0' [xX] [0-9a-fA-F] ([0-9a-fA-F_]* [0-9a-fA-F])? [lL]?;
89 | OCT_LITERAL: '0' '_'* [0-7] ([0-7_]* [0-7])? [lL]?;
90 | BINARY_LITERAL: '0' [bB] [01] ([01_]* [01])? [lL]?;
91 |
92 | FLOAT_LITERAL: (Digits '.' Digits? | '.' Digits) ExponentPart? [fFdD]?
93 | | Digits (ExponentPart [fFdD]? | [fFdD])
94 | ;
95 |
96 | HEX_FLOAT_LITERAL: '0' [xX] (HexDigits '.'? | HexDigits? '.' HexDigits) [pP] [+-]? Digits [fFdD]?;
97 |
98 | BOOL_LITERAL: 'true'
99 | | 'false'
100 | ;
101 |
102 | CHAR_LITERAL: '\'' (~['\\\r\n] | EscapeSequence) '\'';
103 |
104 | STRING_LITERAL: '"' (~["\\\r\n] | EscapeSequence)* '"';
105 |
106 | NULL_LITERAL: 'null';
107 |
108 | // Separators
109 |
110 | LPAREN: '(';
111 | RPAREN: ')';
112 | LBRACE: '{';
113 | RBRACE: '}';
114 | LBRACK: '[';
115 | RBRACK: ']';
116 | SEMI: ';';
117 | COMMA: ',';
118 | DOT: '.';
119 |
120 | // Operators
121 |
122 | ASSIGN: '=';
123 | GT: '>';
124 | LT: '<';
125 | BANG: '!';
126 | TILDE: '~';
127 | QUESTION: '?';
128 | COLON: ':';
129 | EQUAL: '==';
130 | LE: '<=';
131 | GE: '>=';
132 | NOTEQUAL: '!=';
133 | AND: '&&';
134 | OR: '||';
135 | INC: '++';
136 | DEC: '--';
137 | ADD: '+';
138 | SUB: '-';
139 | MUL: '*';
140 | DIV: '/';
141 | BITAND: '&';
142 | BITOR: '|';
143 | CARET: '^';
144 | MOD: '%';
145 |
146 | ADD_ASSIGN: '+=';
147 | SUB_ASSIGN: '-=';
148 | MUL_ASSIGN: '*=';
149 | DIV_ASSIGN: '/=';
150 | AND_ASSIGN: '&=';
151 | OR_ASSIGN: '|=';
152 | XOR_ASSIGN: '^=';
153 | MOD_ASSIGN: '%=';
154 | LSHIFT_ASSIGN: '<<=';
155 | RSHIFT_ASSIGN: '>>=';
156 | URSHIFT_ASSIGN: '>>>=';
157 |
158 | // Java 8 tokens
159 |
160 | ARROW: '->';
161 | COLONCOLON: '::';
162 |
163 | // Additional symbols not defined in the lexical specification
164 |
165 | AT: '@';
166 | ELLIPSIS: '...';
167 |
168 | // Whitespace and comments
169 |
170 | WS: [ \t\r\n\u000C]+ -> channel(HIDDEN);
171 | COMMENT: '/*' .*? '*/' -> channel(HIDDEN);
172 | LINE_COMMENT: '//' ~[\r\n]* -> channel(HIDDEN);
173 |
174 | // Identifiers
175 |
176 | IDENTIFIER: Letter LetterOrDigit*;
177 |
178 | // Fragment rules
179 |
180 | fragment ExponentPart
181 | : [eE] [+-]? Digits
182 | ;
183 |
184 | fragment EscapeSequence
185 | : '\\' [btnfr"'\\]
186 | | '\\' ([0-3]? [0-7])? [0-7]
187 | | '\\' 'u'+ HexDigit HexDigit HexDigit HexDigit
188 | ;
189 |
190 | fragment HexDigits
191 | : HexDigit ((HexDigit | '_')* HexDigit)?
192 | ;
193 |
194 | fragment HexDigit
195 | : [0-9a-fA-F]
196 | ;
197 |
198 | fragment Digits
199 | : [0-9] ([0-9_]* [0-9])?
200 | ;
201 |
202 | fragment LetterOrDigit
203 | : Letter
204 | | [0-9]
205 | ;
206 |
207 | fragment Letter
208 | : [a-zA-Z$_] // these are the "java letters" below 0x7F
209 | | ~[\u0000-\u007F\uD800-\uDBFF] // covers all characters above 0x7F which are not a surrogate
210 | | [\uD800-\uDBFF] [\uDC00-\uDFFF] // covers UTF-16 surrogate pairs encodings for U+10000 to U+10FFFF
211 | ;
212 |
--------------------------------------------------------------------------------
/src/main/antlr4/evolution/analysis/jv/JavaParser.g4:
--------------------------------------------------------------------------------
1 | /*
2 | [The "BSD licence"]
3 | Copyright (c) 2013 Terence Parr, Sam Harwell
4 | Copyright (c) 2017 Ivan Kochurkin (upgrade to Java 8)
5 | All rights reserved.
6 |
7 | Redistribution and use in source and binary forms, with or without
8 | modification, are permitted provided that the following conditions
9 | are met:
10 | 1. Redistributions of source code must retain the above copyright
11 | notice, this list of conditions and the following disclaimer.
12 | 2. Redistributions in binary form must reproduce the above copyright
13 | notice, this list of conditions and the following disclaimer in the
14 | documentation and/or other materials provided with the distribution.
15 | 3. The name of the author may not be used to endorse or promote products
16 | derived from this software without specific prior written permission.
17 |
18 | THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 | IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 | OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 | IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 | NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 | THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 | */
29 |
30 | parser grammar JavaParser;
31 |
32 | options { tokenVocab=JavaLexer; }
33 |
34 | compilationUnit
35 | : packageDeclaration? importDeclaration* typeDeclaration* EOF
36 | ;
37 |
38 | packageDeclaration
39 | : annotation* PACKAGE qualifiedName ';'
40 | ;
41 |
42 | importDeclaration
43 | : IMPORT STATIC? qualifiedName ('.' '*')? ';'
44 | ;
45 |
46 | typeDeclaration
47 | : classOrInterfaceModifier*
48 | (classDeclaration | enumDeclaration | interfaceDeclaration | annotationTypeDeclaration)
49 | | ';'
50 | ;
51 |
52 | modifier
53 | : classOrInterfaceModifier
54 | | NATIVE
55 | | SYNCHRONIZED
56 | | TRANSIENT
57 | | VOLATILE
58 | ;
59 |
60 | classOrInterfaceModifier
61 | : annotation
62 | | PUBLIC
63 | | PROTECTED
64 | | PRIVATE
65 | | STATIC
66 | | ABSTRACT
67 | | FINAL // FINAL for class only -- does not apply to interfaces
68 | | STRICTFP
69 | ;
70 |
71 | variableModifier
72 | : FINAL
73 | | annotation
74 | ;
75 |
76 | classDeclaration
77 | : CLASS IDENTIFIER typeParameters?
78 | (EXTENDS typeType)?
79 | (IMPLEMENTS typeList)?
80 | classBody
81 | ;
82 |
83 | typeParameters
84 | : '<' typeParameter (',' typeParameter)* '>'
85 | ;
86 |
87 | typeParameter
88 | : annotation* IDENTIFIER (EXTENDS typeBound)?
89 | ;
90 |
91 | typeBound
92 | : typeType ('&' typeType)*
93 | ;
94 |
95 | enumDeclaration
96 | : ENUM IDENTIFIER (IMPLEMENTS typeList)? '{' enumConstants? ','? enumBodyDeclarations? '}'
97 | ;
98 |
99 | enumConstants
100 | : enumConstant (',' enumConstant)*
101 | ;
102 |
103 | enumConstant
104 | : annotation* IDENTIFIER arguments? classBody?
105 | ;
106 |
107 | enumBodyDeclarations
108 | : ';' classBodyDeclaration*
109 | ;
110 |
111 | interfaceDeclaration
112 | : INTERFACE IDENTIFIER typeParameters? (EXTENDS typeList)? interfaceBody
113 | ;
114 |
115 | classBody
116 | : '{' classBodyDeclaration* '}'
117 | ;
118 |
119 | interfaceBody
120 | : '{' interfaceBodyDeclaration* '}'
121 | ;
122 |
123 | classBodyDeclaration
124 | : ';'
125 | | STATIC? block
126 | | modifier* memberDeclaration
127 | ;
128 |
129 | memberDeclaration
130 | : methodDeclaration
131 | | genericMethodDeclaration
132 | | fieldDeclaration
133 | | constructorDeclaration
134 | | genericConstructorDeclaration
135 | | interfaceDeclaration
136 | | annotationTypeDeclaration
137 | | classDeclaration
138 | | enumDeclaration
139 | ;
140 |
141 | /* We use rule this even for void methods which cannot have [] after parameters.
142 | This simplifies grammar and we can consider void to be a type, which
143 | renders the [] matching as a context-sensitive issue or a semantic check
144 | for invalid return type after parsing.
145 | */
146 | methodDeclaration
147 | : typeTypeOrVoid IDENTIFIER formalParameters ('[' ']')*
148 | (THROWS qualifiedNameList)?
149 | methodBody
150 | ;
151 |
152 | methodBody
153 | : block
154 | | ';'
155 | ;
156 |
157 | typeTypeOrVoid
158 | : typeType
159 | | VOID
160 | ;
161 |
162 | genericMethodDeclaration
163 | : typeParameters methodDeclaration
164 | ;
165 |
166 | genericConstructorDeclaration
167 | : typeParameters constructorDeclaration
168 | ;
169 |
170 | constructorDeclaration
171 | : IDENTIFIER formalParameters (THROWS qualifiedNameList)? constructorBody=block
172 | ;
173 |
174 | fieldDeclaration
175 | : typeType variableDeclarators ';'
176 | ;
177 |
178 | interfaceBodyDeclaration
179 | : modifier* interfaceMemberDeclaration
180 | | ';'
181 | ;
182 |
183 | interfaceMemberDeclaration
184 | : constDeclaration
185 | | interfaceMethodDeclaration
186 | | genericInterfaceMethodDeclaration
187 | | interfaceDeclaration
188 | | annotationTypeDeclaration
189 | | classDeclaration
190 | | enumDeclaration
191 | ;
192 |
193 | constDeclaration
194 | : typeType constantDeclarator (',' constantDeclarator)* ';'
195 | ;
196 |
197 | constantDeclarator
198 | : IDENTIFIER ('[' ']')* '=' variableInitializer
199 | ;
200 |
201 | // see matching of [] comment in methodDeclaratorRest
202 | // methodBody from Java8
203 | interfaceMethodDeclaration
204 | : interfaceMethodModifier* (typeTypeOrVoid | typeParameters annotation* typeTypeOrVoid)
205 | IDENTIFIER formalParameters ('[' ']')* (THROWS qualifiedNameList)? methodBody
206 | ;
207 |
208 | // Java8
209 | interfaceMethodModifier
210 | : annotation
211 | | PUBLIC
212 | | ABSTRACT
213 | | DEFAULT
214 | | STATIC
215 | | STRICTFP
216 | ;
217 |
218 | genericInterfaceMethodDeclaration
219 | : typeParameters interfaceMethodDeclaration
220 | ;
221 |
222 | variableDeclarators
223 | : variableDeclarator (',' variableDeclarator)*
224 | ;
225 |
226 | variableDeclarator
227 | : variableDeclaratorId ('=' variableInitializer)?
228 | ;
229 |
230 | variableDeclaratorId
231 | : IDENTIFIER ('[' ']')*
232 | ;
233 |
234 | variableInitializer
235 | : arrayInitializer
236 | | expression
237 | ;
238 |
239 | arrayInitializer
240 | : '{' (variableInitializer (',' variableInitializer)* (',')? )? '}'
241 | ;
242 |
243 | classOrInterfaceType
244 | : IDENTIFIER typeArguments? ('.' IDENTIFIER typeArguments?)*
245 | ;
246 |
247 | typeArgument
248 | : typeType
249 | | '?' ((EXTENDS | SUPER) typeType)?
250 | ;
251 |
252 | qualifiedNameList
253 | : qualifiedName (',' qualifiedName)*
254 | ;
255 |
256 | formalParameters
257 | : '(' formalParameterList? ')'
258 | ;
259 |
260 | formalParameterList
261 | : formalParameter (',' formalParameter)* (',' lastFormalParameter)?
262 | | lastFormalParameter
263 | ;
264 |
265 | formalParameter
266 | : variableModifier* typeType variableDeclaratorId
267 | ;
268 |
269 | lastFormalParameter
270 | : variableModifier* typeType '...' variableDeclaratorId
271 | ;
272 |
273 | qualifiedName
274 | : IDENTIFIER ('.' IDENTIFIER)*
275 | ;
276 |
277 | literal
278 | : integerLiteral
279 | | floatLiteral
280 | | CHAR_LITERAL
281 | | STRING_LITERAL
282 | | BOOL_LITERAL
283 | | NULL_LITERAL
284 | ;
285 |
286 | integerLiteral
287 | : DECIMAL_LITERAL
288 | | HEX_LITERAL
289 | | OCT_LITERAL
290 | | BINARY_LITERAL
291 | ;
292 |
293 | floatLiteral
294 | : FLOAT_LITERAL
295 | | HEX_FLOAT_LITERAL
296 | ;
297 |
298 | // ANNOTATIONS
299 |
300 | annotation
301 | : '@' qualifiedName ('(' ( elementValuePairs | elementValue )? ')')?
302 | ;
303 |
304 | elementValuePairs
305 | : elementValuePair (',' elementValuePair)*
306 | ;
307 |
308 | elementValuePair
309 | : IDENTIFIER '=' elementValue
310 | ;
311 |
312 | elementValue
313 | : expression
314 | | annotation
315 | | elementValueArrayInitializer
316 | ;
317 |
318 | elementValueArrayInitializer
319 | : '{' (elementValue (',' elementValue)*)? (',')? '}'
320 | ;
321 |
322 | annotationTypeDeclaration
323 | : '@' INTERFACE IDENTIFIER annotationTypeBody
324 | ;
325 |
326 | annotationTypeBody
327 | : '{' (annotationTypeElementDeclaration)* '}'
328 | ;
329 |
330 | annotationTypeElementDeclaration
331 | : modifier* annotationTypeElementRest
332 | | ';' // this is not allowed by the grammar, but apparently allowed by the actual compiler
333 | ;
334 |
335 | annotationTypeElementRest
336 | : typeType annotationMethodOrConstantRest ';'
337 | | classDeclaration ';'?
338 | | interfaceDeclaration ';'?
339 | | enumDeclaration ';'?
340 | | annotationTypeDeclaration ';'?
341 | ;
342 |
343 | annotationMethodOrConstantRest
344 | : annotationMethodRest
345 | | annotationConstantRest
346 | ;
347 |
348 | annotationMethodRest
349 | : IDENTIFIER '(' ')' defaultValue?
350 | ;
351 |
352 | annotationConstantRest
353 | : variableDeclarators
354 | ;
355 |
356 | defaultValue
357 | : DEFAULT elementValue
358 | ;
359 |
360 | // STATEMENTS / BLOCKS
361 |
362 | block
363 | : '{' blockStatement* '}'
364 | ;
365 |
366 | blockStatement
367 | : localVariableDeclaration ';'
368 | | statement
369 | | localTypeDeclaration
370 | ;
371 |
372 | localVariableDeclaration
373 | : variableModifier* typeType variableDeclarators
374 | ;
375 |
376 | localTypeDeclaration
377 | : classOrInterfaceModifier*
378 | (classDeclaration | interfaceDeclaration)
379 | | ';'
380 | ;
381 |
382 | statement
383 | : blockLabel=block
384 | | ASSERT expression (':' expression)? ';'
385 | | IF parExpression statement (ELSE statement)?
386 | | FOR '(' forControl ')' statement
387 | | WHILE parExpression statement
388 | | DO statement WHILE parExpression ';'
389 | | TRY block (catchClause+ finallyBlock? | finallyBlock)
390 | | TRY resourceSpecification block catchClause* finallyBlock?
391 | | SWITCH parExpression '{' switchBlockStatementGroup* switchLabel* '}'
392 | | SYNCHRONIZED parExpression block
393 | | RETURN expression? ';'
394 | | THROW expression ';'
395 | | BREAK IDENTIFIER? ';'
396 | | CONTINUE IDENTIFIER? ';'
397 | | SEMI
398 | | statementExpression=expression ';'
399 | | identifierLabel=IDENTIFIER ':' statement
400 | ;
401 |
402 | catchClause
403 | : CATCH '(' variableModifier* catchType IDENTIFIER ')' block
404 | ;
405 |
406 | catchType
407 | : qualifiedName ('|' qualifiedName)*
408 | ;
409 |
410 | finallyBlock
411 | : FINALLY block
412 | ;
413 |
414 | resourceSpecification
415 | : '(' resources ';'? ')'
416 | ;
417 |
418 | resources
419 | : resource (';' resource)*
420 | ;
421 |
422 | resource
423 | : variableModifier* classOrInterfaceType variableDeclaratorId '=' expression
424 | ;
425 |
426 | /** Matches cases then statements, both of which are mandatory.
427 | * To handle empty cases at the end, we add switchLabel* to statement.
428 | */
429 | switchBlockStatementGroup
430 | : switchLabel+ blockStatement+
431 | ;
432 |
433 | switchLabel
434 | : CASE (constantExpression=expression | enumConstantName=IDENTIFIER) ':'
435 | | DEFAULT ':'
436 | ;
437 |
438 | forControl
439 | : enhancedForControl
440 | | forInit? ';' expression? ';' forUpdate=expressionList?
441 | ;
442 |
443 | forInit
444 | : localVariableDeclaration
445 | | expressionList
446 | ;
447 |
448 | enhancedForControl
449 | : variableModifier* typeType variableDeclaratorId ':' expression
450 | ;
451 |
452 | // EXPRESSIONS
453 |
454 | parExpression
455 | : '(' expression ')'
456 | ;
457 |
458 | expressionList
459 | : expression (',' expression)*
460 | ;
461 |
462 | methodCall
463 | : IDENTIFIER '(' expressionList? ')'
464 | ;
465 |
466 | expression
467 | : primary
468 | | expression bop='.'
469 | ( IDENTIFIER
470 | | methodCall
471 | | THIS
472 | | NEW nonWildcardTypeArguments? innerCreator
473 | | SUPER superSuffix
474 | | explicitGenericInvocation
475 | )
476 | | expression '[' expression ']'
477 | | methodCall
478 | | NEW creator
479 | | '(' typeType ')' expression
480 | | expression postfix=('++' | '--')
481 | | prefix=('+'|'-'|'++'|'--') expression
482 | | prefix=('~'|'!') expression
483 | | expression bop=('*'|'/'|'%') expression
484 | | expression bop=('+'|'-') expression
485 | | expression ('<' '<' | '>' '>' '>' | '>' '>') expression
486 | | expression bop=('<=' | '>=' | '>' | '<') expression
487 | | expression bop=INSTANCEOF typeType
488 | | expression bop=('==' | '!=') expression
489 | | expression bop='&' expression
490 | | expression bop='^' expression
491 | | expression bop='|' expression
492 | | expression bop='&&' expression
493 | | expression bop='||' expression
494 | | expression bop='?' expression ':' expression
495 | | expression
496 | bop=('=' | '+=' | '-=' | '*=' | '/=' | '&=' | '|=' | '^=' | '>>=' | '>>>=' | '<<=' | '%=')
497 | expression
498 | | lambdaExpression // Java8
499 |
500 | // Java 8 methodReference
501 | | expression '::' typeArguments? IDENTIFIER
502 | | typeType '::' (typeArguments? IDENTIFIER | NEW)
503 | | classType '::' typeArguments? NEW
504 | ;
505 |
506 | // Java8
507 | lambdaExpression
508 | : lambdaParameters '->' lambdaBody
509 | ;
510 |
511 | // Java8
512 | lambdaParameters
513 | : IDENTIFIER
514 | | '(' formalParameterList? ')'
515 | | '(' IDENTIFIER (',' IDENTIFIER)* ')'
516 | ;
517 |
518 | // Java8
519 | lambdaBody
520 | : expression
521 | | block
522 | ;
523 |
524 | primary
525 | : '(' expression ')'
526 | | THIS
527 | | SUPER
528 | | literal
529 | | IDENTIFIER
530 | | typeTypeOrVoid '.' CLASS
531 | | nonWildcardTypeArguments (explicitGenericInvocationSuffix | THIS arguments)
532 | ;
533 |
534 | classType
535 | : (classOrInterfaceType '.')? annotation* IDENTIFIER typeArguments?
536 | ;
537 |
538 | creator
539 | : nonWildcardTypeArguments createdName classCreatorRest
540 | | createdName (arrayCreatorRest | classCreatorRest)
541 | ;
542 |
543 | createdName
544 | : IDENTIFIER typeArgumentsOrDiamond? ('.' IDENTIFIER typeArgumentsOrDiamond?)*
545 | | primitiveType
546 | ;
547 |
548 | innerCreator
549 | : IDENTIFIER nonWildcardTypeArgumentsOrDiamond? classCreatorRest
550 | ;
551 |
552 | arrayCreatorRest
553 | : '[' (']' ('[' ']')* arrayInitializer | expression ']' ('[' expression ']')* ('[' ']')*)
554 | ;
555 |
556 | classCreatorRest
557 | : arguments classBody?
558 | ;
559 |
560 | explicitGenericInvocation
561 | : nonWildcardTypeArguments explicitGenericInvocationSuffix
562 | ;
563 |
564 | typeArgumentsOrDiamond
565 | : '<' '>'
566 | | typeArguments
567 | ;
568 |
569 | nonWildcardTypeArgumentsOrDiamond
570 | : '<' '>'
571 | | nonWildcardTypeArguments
572 | ;
573 |
574 | nonWildcardTypeArguments
575 | : '<' typeList '>'
576 | ;
577 |
578 | typeList
579 | : typeType (',' typeType)*
580 | ;
581 |
582 | typeType
583 | : annotation? (classOrInterfaceType | primitiveType) ('[' ']')*
584 | ;
585 |
586 | primitiveType
587 | : BOOLEAN
588 | | CHAR
589 | | BYTE
590 | | SHORT
591 | | INT
592 | | LONG
593 | | FLOAT
594 | | DOUBLE
595 | ;
596 |
597 | typeArguments
598 | : '<' typeArgument (',' typeArgument)* '>'
599 | ;
600 |
601 | superSuffix
602 | : arguments
603 | | '.' IDENTIFIER arguments?
604 | ;
605 |
606 | explicitGenericInvocationSuffix
607 | : SUPER superSuffix
608 | | IDENTIFIER arguments
609 | ;
610 |
611 | arguments
612 | : '(' expressionList? ')'
613 | ;
--------------------------------------------------------------------------------
/src/main/antlr4/evolution/analysis/sql/Sql.g4:
--------------------------------------------------------------------------------
1 | /*
2 | * The MIT License (MIT)
3 | *
4 | * Copyright (c) 2014 by Bart Kiers
5 | *
6 | * Permission is hereby granted, free of charge, to any person
7 | * obtaining a copy of this software and associated documentation
8 | * files (the "Software"), to deal in the Software without
9 | * restriction, including without limitation the rights to use,
10 | * copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | * copies of the Software, and to permit persons to whom the
12 | * Software is furnished to do so, subject to the following
13 | * conditions:
14 | *
15 | * The above copyright notice and this permission notice shall be
16 | * included in all copies or substantial portions of the Software.
17 | *
18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
20 | * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
22 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
23 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
25 | * OTHER DEALINGS IN THE SOFTWARE.
26 | *
27 | * Project : sqlite-parser; an ANTLR4 grammar for SQLite
28 | * https://github.com/bkiers/sqlite-parser
29 | * Developed by : Bart Kiers, bart@big-o.nl
30 | */
31 | grammar Sql;
32 |
33 | parse
34 | : ( sql_stmt_list | error )* EOF
35 | ;
36 |
37 | error
38 | : UNEXPECTED_CHAR
39 | {
40 | throw new RuntimeException("UNEXPECTED_CHAR=" + $UNEXPECTED_CHAR.text);
41 | }
42 | ;
43 |
44 | sql_stmt_list
45 | : ';'* sql_stmt ( ';' + sql_stmt )* ';'*
46 | ;
47 |
48 | sql_stmt
49 | : ( K_EXPLAIN ( K_QUERY K_PLAN )? )? ( alter_table_stmt
50 | | analyze_stmt
51 | | attach_stmt
52 | | begin_stmt
53 | | commit_stmt
54 | | compound_select_stmt
55 | | create_index_stmt
56 | | create_table_stmt
57 | | create_trigger_stmt
58 | | create_view_stmt
59 | | create_force_view_stmt
60 | | create_virtual_table_stmt
61 | | delete_stmt
62 | | delete_stmt_limited
63 | | detach_stmt
64 | | drop_index_stmt
65 | | drop_table_stmt
66 | | drop_trigger_stmt
67 | | drop_view_stmt
68 | | factored_select_stmt
69 | | insert_stmt
70 | | pragma_stmt
71 | | reindex_stmt
72 | | release_stmt
73 | | rollback_stmt
74 | | savepoint_stmt
75 | | simple_select_stmt
76 | | select_stmt
77 | | update_stmt
78 | | update_stmt_limited
79 | | vacuum_stmt )
80 | ;
81 |
82 | alter_table_stmt
83 | : K_ALTER K_TABLE K_ONLY? ( database_name '.' )? source_table_name
84 | ( K_RENAME K_TO new_table_name
85 | | alter_table_add
86 | | K_ADD K_COLUMN? column_def
87 | | alter_table_add_constraint
88 | )
89 | K_ENABLE?
90 | ;
91 |
92 | alter_table_add_constraint
93 | : K_ADD K_CONSTRAINT any_name table_constraint
94 | ;
95 |
96 | alter_table_add
97 | : K_ADD table_constraint
98 | ;
99 |
100 | analyze_stmt
101 | : K_ANALYZE ( database_name | table_or_index_name | database_name '.' table_or_index_name )?
102 | ;
103 |
104 | attach_stmt
105 | : K_ATTACH K_DATABASE? expr K_AS database_name
106 | ;
107 |
108 | begin_stmt
109 | : K_BEGIN ( K_DEFERRED | K_IMMEDIATE | K_EXCLUSIVE )? ( K_TRANSACTION transaction_name? )?
110 | ;
111 |
112 | commit_stmt
113 | : ( K_COMMIT | K_END ) ( K_TRANSACTION transaction_name? )?
114 | ;
115 |
116 | compound_select_stmt
117 | : ( K_WITH K_RECURSIVE? common_table_expression ( ',' common_table_expression )* )?
118 | select_core ( ( K_UNION K_ALL? | K_INTERSECT | K_EXCEPT ) select_core )+
119 | ( K_ORDER K_BY ordering_term ( ',' ordering_term )* )?
120 | ( K_LIMIT expr ( ( K_OFFSET | ',' ) expr )? )?
121 | ;
122 |
123 | create_index_stmt
124 | : K_CREATE K_UNIQUE? K_INDEX ( K_IF K_NOT K_EXISTS )?
125 | ( database_name '.' )? index_name K_ON table_name '(' indexed_column ( ',' indexed_column )* ')'
126 | ( K_WHERE expr )?
127 | ;
128 |
129 | create_table_stmt
130 | : K_CREATE ( K_TEMP | K_TEMPORARY )? K_TABLE ( K_IF K_NOT K_EXISTS )?
131 | ( database_name '.' )? table_name
132 | ( '(' column_def ( ',' table_constraint | ',' column_def )* ')' ( K_WITHOUT IDENTIFIER )?
133 | | K_AS select_stmt
134 | )
135 | ;
136 |
137 | create_trigger_stmt
138 | : K_CREATE ( K_TEMP | K_TEMPORARY )? K_TRIGGER ( K_IF K_NOT K_EXISTS )?
139 | ( database_name '.' )? trigger_name ( K_BEFORE | K_AFTER | K_INSTEAD K_OF )?
140 | ( K_DELETE | K_INSERT | K_UPDATE ( K_OF column_name ( ',' column_name )* )? ) K_ON ( database_name '.' )? table_name
141 | ( K_FOR K_EACH K_ROW )? ( K_WHEN expr )?
142 | K_BEGIN ( ( update_stmt | insert_stmt | delete_stmt | select_stmt ) ';' )+ K_END
143 | ;
144 |
145 | create_view_stmt
146 | : K_CREATE ( K_TEMP | K_TEMPORARY )? K_VIEW ( K_IF K_NOT K_EXISTS )?
147 | ( database_name '.' )? view_name K_AS select_stmt
148 | ;
149 |
150 | create_force_view_stmt
151 | : K_CREATE ( K_TEMP | K_TEMPORARY )? K_FORCE K_VIEW ( K_IF K_NOT K_EXISTS )?
152 | ( database_name '.' )? view_name ( '(' column_name ( ',' column_name )* ')' )? K_AS select_stmt
153 | ;
154 |
155 |
156 | create_virtual_table_stmt
157 | : K_CREATE K_VIRTUAL K_TABLE ( K_IF K_NOT K_EXISTS )?
158 | ( database_name '.' )? table_name
159 | K_USING module_name ( '(' module_argument ( ',' module_argument )* ')' )?
160 | ;
161 |
162 | delete_stmt
163 | : with_clause? K_DELETE K_FROM qualified_table_name
164 | ( K_WHERE expr )?
165 | ;
166 |
167 | delete_stmt_limited
168 | : with_clause? K_DELETE K_FROM qualified_table_name
169 | ( K_WHERE expr )?
170 | ( ( K_ORDER K_BY ordering_term ( ',' ordering_term )* )?
171 | K_LIMIT expr ( ( K_OFFSET | ',' ) expr )?
172 | )?
173 | ;
174 |
175 | detach_stmt
176 | : K_DETACH K_DATABASE? database_name
177 | ;
178 |
179 | drop_index_stmt
180 | : K_DROP K_INDEX ( K_IF K_EXISTS )? ( database_name '.' )? index_name
181 | ;
182 |
183 | drop_table_stmt
184 | : K_DROP K_TABLE ( K_IF K_EXISTS )? ( database_name '.' )? table_name
185 | ;
186 |
187 | drop_trigger_stmt
188 | : K_DROP K_TRIGGER ( K_IF K_EXISTS )? ( database_name '.' )? trigger_name
189 | ;
190 |
191 | drop_view_stmt
192 | : K_DROP K_VIEW ( K_IF K_EXISTS )? ( database_name '.' )? view_name
193 | ;
194 |
195 | factored_select_stmt
196 | : ( K_WITH K_RECURSIVE? common_table_expression ( ',' common_table_expression )* )?
197 | select_core ( compound_operator select_core )*
198 | ( K_ORDER K_BY ordering_term ( ',' ordering_term )* )?
199 | ( K_LIMIT expr ( ( K_OFFSET | ',' ) expr )? )?
200 | ;
201 |
202 | insert_stmt
203 | : with_clause? ( K_INSERT
204 | | K_REPLACE
205 | | K_INSERT K_OR K_REPLACE
206 | | K_INSERT K_OR K_ROLLBACK
207 | | K_INSERT K_OR K_ABORT
208 | | K_INSERT K_OR K_FAIL
209 | | K_INSERT K_OR K_IGNORE ) K_INTO
210 | ( database_name '.' )? table_name ( '(' column_name ( ',' column_name )* ')' )?
211 | ( K_VALUES '(' expr ( ',' expr )* ')' ( ',' '(' expr ( ',' expr )* ')' )*
212 | | select_stmt
213 | | K_DEFAULT K_VALUES
214 | )
215 | ;
216 |
217 | pragma_stmt
218 | : K_PRAGMA ( database_name '.' )? pragma_name ( '=' pragma_value
219 | | '(' pragma_value ')' )?
220 | ;
221 |
222 | reindex_stmt
223 | : K_REINDEX ( collation_name
224 | | ( database_name '.' )? ( table_name | index_name )
225 | )?
226 | ;
227 |
228 | release_stmt
229 | : K_RELEASE K_SAVEPOINT? savepoint_name
230 | ;
231 |
232 | rollback_stmt
233 | : K_ROLLBACK ( K_TRANSACTION transaction_name? )? ( K_TO K_SAVEPOINT? savepoint_name )?
234 | ;
235 |
236 | savepoint_stmt
237 | : K_SAVEPOINT savepoint_name
238 | ;
239 |
240 | simple_select_stmt
241 | : ( K_WITH K_RECURSIVE? common_table_expression ( ',' common_table_expression )* )?
242 | select_core ( K_ORDER K_BY ordering_term ( ',' ordering_term )* )?
243 | ( K_LIMIT expr ( ( K_OFFSET | ',' ) expr )? )?
244 | ;
245 |
246 | select_stmt
247 | : ( K_WITH K_RECURSIVE? common_table_expression ( ',' common_table_expression )* )?
248 | select_or_values ( compound_operator select_or_values )*
249 | ( K_ORDER K_BY ordering_term ( ',' ordering_term )* )?
250 | ( K_LIMIT expr ( ( K_OFFSET | ',' ) expr )? )?
251 | ;
252 |
253 | select_or_values
254 | : K_SELECT ( K_DISTINCT | K_ALL )? result_column ( ',' result_column )*
255 | ( K_FROM ( table_or_subquery ( ',' table_or_subquery )* | join_clause ) )?
256 | ( K_WHERE expr )?
257 | ( K_GROUP K_BY expr ( ',' expr )* ( K_HAVING expr )? )?
258 | | K_VALUES '(' expr ( ',' expr )* ')' ( ',' '(' expr ( ',' expr )* ')' )*
259 | ;
260 |
261 | update_stmt
262 | : with_clause? K_UPDATE ( K_OR K_ROLLBACK
263 | | K_OR K_ABORT
264 | | K_OR K_REPLACE
265 | | K_OR K_FAIL
266 | | K_OR K_IGNORE )? qualified_table_name
267 | K_SET column_name '=' expr ( ',' column_name '=' expr )* ( K_WHERE expr )?
268 | ;
269 |
270 | update_stmt_limited
271 | : with_clause? K_UPDATE ( K_OR K_ROLLBACK
272 | | K_OR K_ABORT
273 | | K_OR K_REPLACE
274 | | K_OR K_FAIL
275 | | K_OR K_IGNORE )? qualified_table_name
276 | K_SET column_name '=' expr ( ',' column_name '=' expr )* ( K_WHERE expr )?
277 | ( ( K_ORDER K_BY ordering_term ( ',' ordering_term )* )?
278 | K_LIMIT expr ( ( K_OFFSET | ',' ) expr )?
279 | )?
280 | ;
281 |
282 | vacuum_stmt
283 | : K_VACUUM
284 | ;
285 |
286 | column_def
287 | : column_name ( column_constraint | type_name )*
288 | ;
289 |
290 | type_name
291 | : name ( '(' signed_number (any_name)? ')'
292 | | '(' signed_number (any_name)? ',' signed_number (any_name)? ')' )?
293 | ;
294 |
295 | column_constraint
296 | : ( K_CONSTRAINT name )?
297 | ( column_constraint_primary_key
298 | | column_constraint_foreign_key
299 | | column_constraint_not_null
300 | | column_constraint_null
301 | | K_UNIQUE conflict_clause
302 | | K_CHECK '(' expr ')'
303 | | column_default
304 | | K_COLLATE collation_name
305 | )
306 | ;
307 |
308 | column_constraint_primary_key
309 | : K_PRIMARY K_KEY ( K_ASC | K_DESC )? conflict_clause K_AUTOINCREMENT?
310 | ;
311 |
312 | column_constraint_foreign_key
313 | : foreign_key_clause
314 | ;
315 |
316 | column_constraint_not_null
317 | : K_NOT K_NULL conflict_clause
318 | ;
319 |
320 | column_constraint_null
321 | : K_NULL conflict_clause
322 | ;
323 |
324 | column_default
325 | : K_DEFAULT (column_default_value | '(' expr ')' | K_NEXTVAL '(' expr ')' | any_name ) ( '::' any_name+ )?
326 | ;
327 |
328 | column_default_value
329 | : ( signed_number | literal_value )
330 | ;
331 |
332 | conflict_clause
333 | : ( K_ON K_CONFLICT ( K_ROLLBACK
334 | | K_ABORT
335 | | K_FAIL
336 | | K_IGNORE
337 | | K_REPLACE
338 | )
339 | )?
340 | ;
341 |
342 | /*
343 | SQLite understands the following binary operators, in order from highest to
344 | lowest precedence:
345 |
346 | ||
347 | * / %
348 | + -
349 | << >> & |
350 | < <= > >=
351 | = == != <> IS IS NOT IN LIKE GLOB MATCH REGEXP
352 | AND
353 | OR
354 | */
355 | expr
356 | : literal_value
357 | | BIND_PARAMETER
358 | | ( ( database_name '.' )? table_name '.' )? column_name
359 | | unary_operator expr
360 | | expr '||' expr
361 | | expr ( '*' | '/' | '%' ) expr
362 | | expr ( '+' | '-' ) expr
363 | | expr ( '<<' | '>>' | '&' | '|' ) expr
364 | | expr ( '<' | '<=' | '>' | '>=' ) expr
365 | | expr ( '=' | '==' | '!=' | '<>' | K_IS | K_IS K_NOT | K_IN | K_LIKE | K_GLOB | K_MATCH | K_REGEXP ) expr
366 | | expr K_AND expr
367 | | expr K_OR expr
368 | | function_name '(' ( K_DISTINCT? expr ( ',' expr )* | '*' )? ')'
369 | | '(' expr ')'
370 | | K_CAST '(' expr K_AS type_name ')'
371 | | expr K_COLLATE collation_name
372 | | expr K_NOT? ( K_LIKE | K_GLOB | K_REGEXP | K_MATCH ) expr ( K_ESCAPE expr )?
373 | | expr ( K_ISNULL | K_NOTNULL | K_NOT K_NULL )
374 | | expr K_IS K_NOT? expr
375 | | expr K_NOT? K_BETWEEN expr K_AND expr
376 | | expr K_NOT? K_IN ( '(' ( select_stmt
377 | | expr ( ',' expr )*
378 | )?
379 | ')'
380 | | ( database_name '.' )? table_name )
381 | | ( ( K_NOT )? K_EXISTS )? '(' select_stmt ')'
382 | | K_CASE expr? ( K_WHEN expr K_THEN expr )+ ( K_ELSE expr )? K_END
383 | | raise_function
384 | ;
385 |
386 | foreign_key_clause
387 | : K_REFERENCES ( database_name '.' )? foreign_table ( '(' fk_target_column_name ( ',' fk_target_column_name )* ')' )?
388 | ( ( K_ON ( K_DELETE | K_UPDATE ) ( K_SET K_NULL
389 | | K_SET K_DEFAULT
390 | | K_CASCADE
391 | | K_RESTRICT
392 | | K_NO K_ACTION )
393 | | K_MATCH name
394 | )
395 | )*
396 | ( K_NOT? K_DEFERRABLE? ( K_INITIALLY K_DEFERRED | K_INITIALLY K_IMMEDIATE | K_ENABLE K_NOVALIDATE)? K_ENABLE? K_DISABLE? )?
397 | ;
398 |
399 | fk_target_column_name
400 | : name
401 | ;
402 |
403 | raise_function
404 | : K_RAISE '(' ( K_IGNORE
405 | | ( K_ROLLBACK | K_ABORT | K_FAIL ) ',' error_message )
406 | ')'
407 | ;
408 |
409 | indexed_column
410 | : column_name ( K_COLLATE collation_name )? ( K_ASC | K_DESC )?
411 | ;
412 |
413 | table_constraint
414 | : ( K_CONSTRAINT name )?
415 | ( table_constraint_primary_key
416 | | table_constraint_key
417 | | table_constraint_unique
418 | | K_CHECK '(' expr ')'
419 | | table_constraint_foreign_key
420 | )
421 | ;
422 |
423 | table_constraint_primary_key
424 | : K_PRIMARY K_KEY '(' indexed_column ( ',' indexed_column )* ')' conflict_clause
425 | ;
426 |
427 | table_constraint_foreign_key
428 | : K_FOREIGN K_KEY '(' fk_origin_column_name ( ',' fk_origin_column_name )* ')' foreign_key_clause
429 | ;
430 |
431 | table_constraint_unique
432 | : K_UNIQUE K_KEY? name? '(' indexed_column ( ',' indexed_column )* ')' conflict_clause
433 | ;
434 |
435 | table_constraint_key
436 | : K_KEY name? '(' indexed_column ( ',' indexed_column )* ')' conflict_clause
437 | ;
438 |
439 | fk_origin_column_name
440 | : column_name
441 | ;
442 |
443 | with_clause
444 | : K_WITH K_RECURSIVE? cte_table_name K_AS '(' select_stmt ')' ( ',' cte_table_name K_AS '(' select_stmt ')' )*
445 | ;
446 |
447 | qualified_table_name
448 | : ( database_name '.' )? table_name ( K_INDEXED K_BY index_name
449 | | K_NOT K_INDEXED )?
450 | ;
451 |
452 | ordering_term
453 | : expr ( K_COLLATE collation_name )? ( K_ASC | K_DESC )?
454 | ;
455 |
456 | pragma_value
457 | : signed_number
458 | | name
459 | | STRING_LITERAL
460 | ;
461 |
462 | common_table_expression
463 | : table_name ( '(' column_name ( ',' column_name )* ')' )? K_AS '(' select_stmt ')'
464 | ;
465 |
466 | result_column
467 | : '*'
468 | | table_name '.' '*'
469 | | expr ( K_AS? column_alias )?
470 | ;
471 |
472 | table_or_subquery
473 | : ( database_name '.' )? table_name ( K_AS? table_alias )?
474 | ( K_INDEXED K_BY index_name
475 | | K_NOT K_INDEXED )?
476 | | '(' ( table_or_subquery ( ',' table_or_subquery )*
477 | | join_clause )
478 | ')' ( K_AS? table_alias )?
479 | | '(' select_stmt ')' ( K_AS? table_alias )?
480 | ;
481 |
482 | join_clause
483 | : table_or_subquery ( join_operator table_or_subquery join_constraint )*
484 | ;
485 |
486 | join_operator
487 | : ','
488 | | K_NATURAL? ( K_LEFT K_OUTER? | K_INNER | K_CROSS )? K_JOIN
489 | ;
490 |
491 | join_constraint
492 | : ( K_ON expr
493 | | K_USING '(' column_name ( ',' column_name )* ')' )?
494 | ;
495 |
496 | select_core
497 | : K_SELECT ( K_DISTINCT | K_ALL )? result_column ( ',' result_column )*
498 | ( K_FROM ( table_or_subquery ( ',' table_or_subquery )* | join_clause ) )?
499 | ( K_WHERE expr )?
500 | ( K_GROUP K_BY expr ( ',' expr )* ( K_HAVING expr )? )?
501 | | K_VALUES '(' expr ( ',' expr )* ')' ( ',' '(' expr ( ',' expr )* ')' )*
502 | ;
503 |
504 | compound_operator
505 | : K_UNION
506 | | K_UNION K_ALL
507 | | K_INTERSECT
508 | | K_EXCEPT
509 | ;
510 |
511 | cte_table_name
512 | : table_name ( '(' column_name ( ',' column_name )* ')' )?
513 | ;
514 |
515 | signed_number
516 | : ( ( '+' | '-' )? NUMERIC_LITERAL | '*' )
517 | ;
518 |
519 | literal_value
520 | : NUMERIC_LITERAL
521 | | STRING_LITERAL
522 | | BLOB_LITERAL
523 | | K_NULL
524 | | K_CURRENT_TIME
525 | | K_CURRENT_DATE
526 | | K_CURRENT_TIMESTAMP
527 | ;
528 |
529 | unary_operator
530 | : '-'
531 | | '+'
532 | | '~'
533 | | K_NOT
534 | ;
535 |
536 | error_message
537 | : STRING_LITERAL
538 | ;
539 |
540 | module_argument // TODO check what exactly is permitted here
541 | : expr
542 | | column_def
543 | ;
544 |
545 | column_alias
546 | : IDENTIFIER
547 | | STRING_LITERAL
548 | ;
549 |
550 | keyword
551 | : K_ABORT
552 | | K_ACTION
553 | | K_ADD
554 | | K_AFTER
555 | | K_ALL
556 | | K_ALTER
557 | | K_ANALYZE
558 | | K_AND
559 | | K_AS
560 | | K_ASC
561 | | K_ATTACH
562 | | K_AUTOINCREMENT
563 | | K_BEFORE
564 | | K_BEGIN
565 | | K_BETWEEN
566 | | K_BY
567 | | K_CASCADE
568 | | K_CASE
569 | | K_CAST
570 | | K_CHECK
571 | | K_COLLATE
572 | | K_COLUMN
573 | | K_COMMIT
574 | | K_CONFLICT
575 | | K_CONSTRAINT
576 | | K_CREATE
577 | | K_CROSS
578 | | K_CURRENT_DATE
579 | | K_CURRENT_TIME
580 | | K_CURRENT_TIMESTAMP
581 | | K_DATABASE
582 | | K_DEFAULT
583 | | K_DEFERRABLE
584 | | K_DEFERRED
585 | | K_DELETE
586 | | K_DESC
587 | | K_DETACH
588 | | K_DISTINCT
589 | | K_DROP
590 | | K_EACH
591 | | K_ELSE
592 | | K_END
593 | | K_ENABLE
594 | | K_ESCAPE
595 | | K_EXCEPT
596 | | K_EXCLUSIVE
597 | | K_EXISTS
598 | | K_EXPLAIN
599 | | K_FAIL
600 | | K_FOR
601 | | K_FOREIGN
602 | | K_FROM
603 | | K_FULL
604 | | K_GLOB
605 | | K_GROUP
606 | | K_HAVING
607 | | K_IF
608 | | K_IGNORE
609 | | K_IMMEDIATE
610 | | K_IN
611 | | K_INDEX
612 | | K_INDEXED
613 | | K_INITIALLY
614 | | K_INNER
615 | | K_INSERT
616 | | K_INSTEAD
617 | | K_INTERSECT
618 | | K_INTO
619 | | K_IS
620 | | K_ISNULL
621 | | K_JOIN
622 | | K_KEY
623 | | K_LEFT
624 | | K_LIKE
625 | | K_LIMIT
626 | | K_MATCH
627 | | K_NATURAL
628 | | K_NO
629 | | K_NOT
630 | | K_NOTNULL
631 | | K_NULL
632 | | K_OF
633 | | K_OFFSET
634 | | K_ON
635 | | K_OR
636 | | K_ORDER
637 | | K_OUTER
638 | | K_PLAN
639 | | K_PRAGMA
640 | | K_PRIMARY
641 | | K_QUERY
642 | | K_RAISE
643 | | K_RECURSIVE
644 | | K_REFERENCES
645 | | K_REGEXP
646 | | K_REINDEX
647 | | K_RELEASE
648 | | K_RENAME
649 | | K_REPLACE
650 | | K_RESTRICT
651 | | K_RIGHT
652 | | K_ROLLBACK
653 | | K_ROW
654 | | K_SAVEPOINT
655 | | K_SELECT
656 | | K_SET
657 | | K_TABLE
658 | | K_TEMP
659 | | K_TEMPORARY
660 | | K_THEN
661 | | K_TO
662 | | K_TRANSACTION
663 | | K_TRIGGER
664 | | K_UNION
665 | | K_UNIQUE
666 | | K_UPDATE
667 | | K_USING
668 | | K_VACUUM
669 | | K_VALUES
670 | | K_VIEW
671 | | K_VIRTUAL
672 | | K_WHEN
673 | | K_WHERE
674 | | K_WITH
675 | | K_WITHOUT
676 | | K_NEXTVAL
677 | ;
678 |
679 | // TODO check all names below
680 |
681 | //[a-zA-Z_0-9\t \-\[\]\=]+
682 | unknown
683 | : .+
684 | ;
685 |
686 | name
687 | : any_name
688 | ;
689 |
690 | function_name
691 | : any_name
692 | ;
693 |
694 | database_name
695 | : any_name
696 | ;
697 |
698 | source_table_name
699 | : any_name
700 | ;
701 |
702 | table_name
703 | : any_name
704 | ;
705 |
706 | table_or_index_name
707 | : any_name
708 | ;
709 |
710 | new_table_name
711 | : any_name
712 | ;
713 |
714 | column_name
715 | : any_name
716 | ;
717 |
718 | collation_name
719 | : any_name
720 | ;
721 |
722 | foreign_table
723 | : any_name
724 | ;
725 |
726 | index_name
727 | : any_name
728 | ;
729 |
730 | trigger_name
731 | : any_name
732 | ;
733 |
734 | view_name
735 | : any_name
736 | ;
737 |
738 | module_name
739 | : any_name
740 | ;
741 |
742 | pragma_name
743 | : any_name
744 | ;
745 |
746 | savepoint_name
747 | : any_name
748 | ;
749 |
750 | table_alias
751 | : any_name
752 | ;
753 |
754 | transaction_name
755 | : any_name
756 | ;
757 |
758 | any_name
759 | : IDENTIFIER
760 | | keyword
761 | | STRING_LITERAL
762 | | '(' any_name ')'
763 | ;
764 |
765 | SCOL : ';';
766 | DOT : '.';
767 | OPEN_PAR : '(';
768 | CLOSE_PAR : ')';
769 | COMMA : ',';
770 | ASSIGN : '=';
771 | STAR : '*';
772 | PLUS : '+';
773 | MINUS : '-';
774 | TILDE : '~';
775 | PIPE2 : '||';
776 | DIV : '/';
777 | MOD : '%';
778 | LT2 : '<<';
779 | GT2 : '>>';
780 | AMP : '&';
781 | PIPE : '|';
782 | LT : '<';
783 | LT_EQ : '<=';
784 | GT : '>';
785 | GT_EQ : '>=';
786 | EQ : '==';
787 | NOT_EQ1 : '!=';
788 | NOT_EQ2 : '<>';
789 |
790 | // http://www.sqlite.org/lang_keywords.html
791 | K_ABORT : A B O R T;
792 | K_ACTION : A C T I O N;
793 | K_ADD : A D D;
794 | K_AFTER : A F T E R;
795 | K_ALL : A L L;
796 | K_ALTER : A L T E R;
797 | K_ANALYZE : A N A L Y Z E;
798 | K_AND : A N D;
799 | K_AS : A S;
800 | K_ASC : A S C;
801 | K_ATTACH : A T T A C H;
802 | K_AUTOINCREMENT : A U T O I N C R E M E N T;
803 | K_BEFORE : B E F O R E;
804 | K_BEGIN : B E G I N;
805 | K_BETWEEN : B E T W E E N;
806 | K_BY : B Y;
807 | K_CASCADE : C A S C A D E;
808 | K_CASE : C A S E;
809 | K_CAST : C A S T;
810 | K_CHECK : C H E C K;
811 | K_COLLATE : C O L L A T E;
812 | K_COLUMN : C O L U M N;
813 | K_COMMIT : C O M M I T;
814 | K_CONFLICT : C O N F L I C T;
815 | K_CONSTRAINT : C O N S T R A I N T;
816 | K_CREATE : C R E A T E;
817 | K_CROSS : C R O S S;
818 | K_CURRENT_DATE : C U R R E N T '_' D A T E;
819 | K_CURRENT_TIME : C U R R E N T '_' T I M E;
820 | K_CURRENT_TIMESTAMP : C U R R E N T '_' T I M E S T A M P;
821 | K_DATABASE : D A T A B A S E;
822 | K_DEFAULT : D E F A U L T;
823 | K_DEFERRABLE : D E F E R R A B L E;
824 | K_DEFERRED : D E F E R R E D;
825 | K_DELETE : D E L E T E;
826 | K_DESC : D E S C;
827 | K_DETACH : D E T A C H;
828 | K_DISTINCT : D I S T I N C T;
829 | K_DROP : D R O P;
830 | K_EACH : E A C H;
831 | K_ELSE : E L S E;
832 | K_END : E N D;
833 | K_ENABLE : E N A B L E;
834 | K_DISABLE: D I S A B L E;
835 | K_NOVALIDATE: N O V A L I D A T E;
836 | K_ESCAPE : E S C A P E;
837 | K_EXCEPT : E X C E P T;
838 | K_EXCLUSIVE : E X C L U S I V E;
839 | K_EXISTS : E X I S T S;
840 | K_EXPLAIN : E X P L A I N;
841 | K_FAIL : F A I L;
842 | K_FOR : F O R;
843 | K_FOREIGN : F O R E I G N;
844 | K_FROM : F R O M;
845 | K_FULL : F U L L;
846 | K_GLOB : G L O B;
847 | K_GROUP : G R O U P;
848 | K_HAVING : H A V I N G;
849 | K_IF : I F;
850 | K_IGNORE : I G N O R E;
851 | K_IMMEDIATE : I M M E D I A T E;
852 | K_IN : I N;
853 | K_INDEX : I N D E X;
854 | K_INDEXED : I N D E X E D;
855 | K_INITIALLY : I N I T I A L L Y;
856 | K_INNER : I N N E R;
857 | K_INSERT : I N S E R T;
858 | K_INSTEAD : I N S T E A D;
859 | K_INTERSECT : I N T E R S E C T;
860 | K_INTO : I N T O;
861 | K_IS : I S;
862 | K_ISNULL : I S N U L L;
863 | K_JOIN : J O I N;
864 | K_KEY : K E Y;
865 | K_LEFT : L E F T;
866 | K_LIKE : L I K E;
867 | K_LIMIT : L I M I T;
868 | K_MATCH : M A T C H;
869 | K_NATURAL : N A T U R A L;
870 | K_NEXTVAL : N E X T V A L;
871 | K_NO : N O;
872 | K_NOT : N O T;
873 | K_NOTNULL : N O T N U L L;
874 | K_NULL : N U L L;
875 | K_OF : O F;
876 | K_OFFSET : O F F S E T;
877 | K_ON : O N;
878 | K_ONLY : O N L Y;
879 | K_OR : O R;
880 | K_ORDER : O R D E R;
881 | K_OUTER : O U T E R;
882 | K_PLAN : P L A N;
883 | K_PRAGMA : P R A G M A;
884 | K_PRIMARY : P R I M A R Y;
885 | K_QUERY : Q U E R Y;
886 | K_RAISE : R A I S E;
887 | K_RECURSIVE : R E C U R S I V E;
888 | K_REFERENCES : R E F E R E N C E S;
889 | K_REGEXP : R E G E X P;
890 | K_REINDEX : R E I N D E X;
891 | K_RELEASE : R E L E A S E;
892 | K_RENAME : R E N A M E;
893 | K_REPLACE : R E P L A C E;
894 | K_RESTRICT : R E S T R I C T;
895 | K_RIGHT : R I G H T;
896 | K_ROLLBACK : R O L L B A C K;
897 | K_ROW : R O W;
898 | K_SAVEPOINT : S A V E P O I N T;
899 | K_SELECT : S E L E C T;
900 | K_SET : S E T;
901 | K_TABLE : T A B L E;
902 | K_TEMP : T E M P;
903 | K_TEMPORARY : T E M P O R A R Y;
904 | K_THEN : T H E N;
905 | K_TO : T O;
906 | K_TRANSACTION : T R A N S A C T I O N;
907 | K_TRIGGER : T R I G G E R;
908 | K_UNION : U N I O N;
909 | K_UNIQUE : U N I Q U E;
910 | K_UPDATE : U P D A T E;
911 | K_USING : U S I N G;
912 | K_VACUUM : V A C U U M;
913 | K_VALUES : V A L U E S;
914 | K_VIEW : V I E W;
915 | K_FORCE : F O R C E;
916 | K_VIRTUAL : V I R T U A L;
917 | K_WHEN : W H E N;
918 | K_WHERE : W H E R E;
919 | K_WITH : W I T H;
920 | K_WITHOUT : W I T H O U T;
921 |
922 | IDENTIFIER
923 | : '"' (~'"' | '""')* '"'
924 | | '`' (~'`' | '``')* '`'
925 | | '[' ~']'* ']'
926 | | [a-zA-Z_] [a-zA-Z_0-9]* // TODO check: needs more chars in set
927 | ;
928 |
929 | NUMERIC_LITERAL
930 | : DIGIT+ ( '.' DIGIT* )? ( E [-+]? DIGIT+ )?
931 | | '.' DIGIT+ ( E [-+]? DIGIT+ )?
932 | ;
933 |
934 | BIND_PARAMETER
935 | : '?' DIGIT*
936 | | [:@$] IDENTIFIER
937 | ;
938 |
939 | STRING_LITERAL
940 | : '\'' ( ~'\'' | '\'\'' )* '\''
941 | ;
942 |
943 | BLOB_LITERAL
944 | : X STRING_LITERAL
945 | ;
946 |
947 | SINGLE_LINE_COMMENT
948 | : '--' ~[\r\n]* -> channel(HIDDEN)
949 | ;
950 |
951 | MULTILINE_COMMENT
952 | : '/*' .*? ( '*/' | EOF ) -> channel(HIDDEN)
953 | ;
954 |
955 | SPACES
956 | : [ \u000B\t\r\n] -> channel(HIDDEN)
957 | ;
958 |
959 | UNEXPECTED_CHAR
960 | : .
961 | ;
962 |
963 | fragment DIGIT : [0-9];
964 |
965 | fragment A : [aA];
966 | fragment B : [bB];
967 | fragment C : [cC];
968 | fragment D : [dD];
969 | fragment E : [eE];
970 | fragment F : [fF];
971 | fragment G : [gG];
972 | fragment H : [hH];
973 | fragment I : [iI];
974 | fragment J : [jJ];
975 | fragment K : [kK];
976 | fragment L : [lL];
977 | fragment M : [mM];
978 | fragment N : [nN];
979 | fragment O : [oO];
980 | fragment P : [pP];
981 | fragment Q : [qQ];
982 | fragment R : [rR];
983 | fragment S : [sS];
984 | fragment T : [tT];
985 | fragment U : [uU];
986 | fragment V : [vV];
987 | fragment W : [wW];
988 | fragment X : [xX];
989 | fragment Y : [yY];
990 | fragment Z : [zZ];
991 |
--------------------------------------------------------------------------------
/src/main/docker/Dockerfile:
--------------------------------------------------------------------------------
1 | #
2 | # Copyright (c) 2018 Oracle and/or its affiliates. All rights reserved.
3 | #
4 | # Licensed under the Apache License, Version 2.0 (the "License");
5 | # you may not use this file except in compliance with the License.
6 | # You may obtain a copy of the License at
7 | #
8 | # http://www.apache.org/licenses/LICENSE-2.0
9 | #
10 | # Unless required by applicable law or agreed to in writing, software
11 | # distributed under the License is distributed on an "AS IS" BASIS,
12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | # See the License for the specific language governing permissions and
14 | # limitations under the License.
15 | #
16 |
17 | FROM openjdk:8-jre-alpine
18 |
19 | RUN mkdir /app
20 | COPY target/dependencies_java-1.0.jar /app
21 | COPY target/libs /app/libs
22 |
23 | EXPOSE 8080
24 |
25 | ENTRYPOINT ["java"]
26 | CMD ["-jar", "/app/dependencies_java-1.0.jar"]
27 |
28 | #docker build -t dependencies_java -f src/main/docker/Dockerfile .
29 | #docker run --rm -it -p 8080:8080 -v /Users/xfwu/Workspace/petclient:/workspace dependencies_java bash
--------------------------------------------------------------------------------
/src/main/java/evolution/Main.java:
--------------------------------------------------------------------------------
1 | package evolution;
2 |
3 |
4 | import evolution.analysis.jv.ParseClassService;
5 | import evolution.configuration.ConfigReader;
6 | import evolution.factory.ServiceFactory;
7 | import evolution.factory.daoparser.DaoParserProvider;
8 | import io.helidon.config.Config;
9 | import io.helidon.webserver.*;
10 | import io.helidon.webserver.json.JsonSupport;
11 |
12 | import javax.json.Json;
13 | import javax.json.JsonObject;
14 | import java.io.IOException;
15 | import java.net.URISyntaxException;
16 | import java.net.URL;
17 | import java.nio.file.Path;
18 | import java.nio.file.Paths;
19 | import java.util.logging.LogManager;
20 |
21 | /**
22 | * Simple rest application.
23 | */
24 | public final class Main {
25 |
26 | /**
27 | * Cannot be instantiated.
28 | */
29 | private Main() { }
30 |
31 | /**
32 | * Creates new {@link Routing}.
33 | *
34 | * @return the new instance
35 | */
36 | private static Routing createRouting() {
37 | DaoParserProvider reader = new ConfigReader();
38 | ServiceFactory factory = new ServiceFactory(reader);
39 |
40 | return Routing.builder()
41 | .register(JsonSupport.get())
42 | .register("/greet", new GreetService())
43 | .register("/analysis/class", factory.createParseClassService())
44 | .register("/analysis/package", factory.createParsePackageService())
45 | .build();
46 | }
47 |
48 | /**
49 | * Application main entry point.
50 | * @param args command line arguments.
51 | * @throws IOException if there are problems reading logging properties
52 | */
53 | public static void main(final String[] args) throws IOException {
54 | System.out.println("start server");
55 | startServer();
56 | }
57 |
58 | /**
59 | * Start the server.
60 | * @return the created {@link WebServer} instance
61 | * @throws IOException if there are problems reading logging properties
62 | */
63 | protected static WebServer startServer() throws IOException {
64 |
65 | // load logging configuration
66 | LogManager.getLogManager().readConfiguration(
67 | Main.class.getResourceAsStream("/logging.properties"));
68 |
69 | // By default this will pick up application.yaml from the classpath
70 | Config config = Config.create();
71 |
72 | // Get webserver config from the "server" section of application.yaml
73 | ServerConfiguration serverConfig =
74 | ServerConfiguration.fromConfig(config.get("server"));
75 |
76 | WebServer server = WebServer.create(serverConfig, createRouting());
77 |
78 | // Start the server and print some info.
79 | server.start().thenAccept(ws -> {
80 | System.out.println(
81 | "WEB server is up! http://localhost:" + ws.port());
82 | });
83 |
84 | // Server threads are not demon. NO need to block. Just react.
85 | server.whenShutdown().thenRun(()
86 | -> System.out.println("WEB server is DOWN. Good bye!"));
87 |
88 | return server;
89 | }
90 |
91 | static Path resourcePath(String resourceName) throws URISyntaxException {
92 | URL resourceUrl = Thread.currentThread().getContextClassLoader().getResource(resourceName);
93 | if (resourceUrl != null) {
94 | return Paths.get(resourceUrl.toURI());
95 | } else {
96 | return null;
97 | }
98 | }
99 |
100 | public static class GreetService implements Service {
101 |
102 |
103 | private String greeting = "Hello";
104 | /**
105 | * A service registers itself by updating the routine rules.
106 | * @param rules the routing rules.
107 | */
108 | @Override
109 | public final void update(final Routing.Rules rules) {
110 | rules
111 | .get("/{name}", this::getMessage)
112 | .put("/greeting/{greeting}", this::updateGreeting);
113 | }
114 |
115 | /**
116 | * Return a greeting message using the name that was provided.
117 | * @param request the server request
118 | * @param response the server response
119 | */
120 | private void getMessage(final ServerRequest request,
121 | final ServerResponse response) {
122 | String name = request.path().param("name");
123 | String msg = String.format("%s %s!", greeting, name);
124 |
125 | JsonObject returnObject = Json.createObjectBuilder()
126 | .add("message", msg)
127 | .build();
128 | response.send(returnObject);
129 | }
130 |
131 | /**
132 | * Set the greeting to use in future messages.
133 | * @param request the server request
134 | * @param response the server response
135 | */
136 | private void updateGreeting(final ServerRequest request,
137 | final ServerResponse response) {
138 | greeting = request.path().param("greeting");
139 |
140 | JsonObject returnObject = Json.createObjectBuilder()
141 | .add("greeting", greeting)
142 | .build();
143 | response.send(returnObject);
144 | }
145 | }
146 | }
147 |
--------------------------------------------------------------------------------
/src/main/java/evolution/analysis/jv/ParseClassApp.java:
--------------------------------------------------------------------------------
1 | package evolution.analysis.jv;
2 |
3 | import evolution.analysis.jv.calls.JavaCallApp;
4 | import evolution.analysis.jv.calls.JavaDaoParser;
5 | import evolution.analysis.jv.identifier.JavaClassQuery;
6 | import evolution.analysis.jv.identifier.JavaIdentifierApp;
7 | import evolution.store.Neo4JDriverFactory;
8 | import evolution.store.StoreManager;
9 | import io.helidon.config.Config;
10 | import org.neo4j.driver.v1.Driver;
11 |
12 | import java.io.IOException;
13 | import java.nio.file.Path;
14 | import java.nio.file.Paths;
15 | import java.util.List;
16 | import java.util.logging.Logger;
17 |
18 | public class ParseClassApp {
19 |
20 | private static final Logger LOGGER = Logger.getLogger(ParseClassApp.class.getName());
21 | private String neo4jServer = Config.create().get("app").get("neo4j-server").asString("localhost");
22 | public ParseClassApp(){}
23 | public ParseClassApp(String neo4jServer){
24 | this.neo4jServer = neo4jServer;
25 | }
26 | public void parse(String rootDir, String clz, JavaDaoParser daoParser) throws IOException {
27 | Driver driver = Neo4JDriverFactory.create(neo4jServer);
28 | JavaClassQuery classQuery = new JavaClassQuery(driver);
29 | List clzs = classQuery.load();
30 | StoreManager store = new StoreManager(driver);
31 | String deleteState=String.format("MATCH (c1:Class{fullname:'%s'})-[r:Has]->(m2) DETACH DELETE c1,r,m2",clz);
32 | System.out.println("Delete: " + clz);
33 | store.update(deleteState);
34 | String file = String.format("%s/src/main/java/%s.java",rootDir,clz.replaceAll("\\.","/"));
35 |
36 | Path path = Paths.get(file);
37 | new JavaIdentifierApp(driver).parse(path);
38 | new JavaCallApp(driver, daoParser).parse(path,clzs);
39 | driver.close();
40 | LOGGER.info("finished and close driver.");
41 | }
42 |
43 | }
44 |
--------------------------------------------------------------------------------
/src/main/java/evolution/analysis/jv/ParseClassService.java:
--------------------------------------------------------------------------------
1 | package evolution.analysis.jv;
2 |
3 | import evolution.analysis.jv.calls.plugins.MyBatisParser;
4 | import evolution.factory.daoparser.JavaDaoParserFactory;
5 | import io.helidon.config.Config;
6 | import io.helidon.webserver.Routing;
7 | import io.helidon.webserver.ServerRequest;
8 | import io.helidon.webserver.ServerResponse;
9 | import io.helidon.webserver.Service;
10 |
11 | import javax.json.Json;
12 | import javax.json.JsonObject;
13 |
14 | public class ParseClassService implements Service {
15 |
16 | /**
17 | * This gets config from application.yaml on classpath
18 | * and uses "app" section.
19 | */
20 | private final Config CONFIG = Config.create().get("app");
21 | private final String rootDir = CONFIG.get("root").asString("~/workspace");
22 | private final ParseClassApp clzParser = new ParseClassApp();
23 | private final JavaDaoParserFactory javaDaoParserFactory;
24 |
25 | public ParseClassService(JavaDaoParserFactory javaDaoParserFactory) {
26 |
27 | this.javaDaoParserFactory = javaDaoParserFactory;
28 | }
29 |
30 | @Override
31 | public void update(Routing.Rules rules) {
32 | rules
33 | .post("/{class}", this::parse);
34 | }
35 |
36 | /**
37 | * Return a wordly greeting message.
38 | * @param request the server request
39 | * @param response the server response
40 | */
41 | private void parse(final ServerRequest request,
42 | final ServerResponse response) {
43 | String clz = request.path().param("class");
44 |
45 | try {
46 | clzParser.parse(rootDir,clz, javaDaoParserFactory.createDaoParser());
47 | JsonObject returnObject = Json.createObjectBuilder()
48 | .add("message", clz)
49 | .build();
50 | response.send(returnObject);
51 | } catch (Exception e) {
52 | e.printStackTrace();
53 | JsonObject returnObject = Json.createObjectBuilder()
54 | .add("message", e.getMessage())
55 | .build();
56 | response.send(returnObject);
57 | }
58 |
59 | }
60 |
61 |
62 | }
63 |
--------------------------------------------------------------------------------
/src/main/java/evolution/analysis/jv/ParsePackageService.java:
--------------------------------------------------------------------------------
1 | package evolution.analysis.jv;
2 |
3 | import evolution.analysis.jv.calls.JavaCallApp;
4 | import evolution.analysis.jv.calls.JavaDaoParser;
5 | import evolution.factory.daoparser.JavaDaoParserFactory;
6 | import evolution.analysis.jv.calls.plugins.JavaDaoStringParser;
7 | import evolution.analysis.jv.identifier.JavaClassQuery;
8 | import evolution.analysis.jv.identifier.JavaIdentifierApp;
9 | import evolution.store.Neo4JDriverFactory;
10 | import io.helidon.config.Config;
11 | import io.helidon.webserver.Routing;
12 | import io.helidon.webserver.ServerRequest;
13 | import io.helidon.webserver.ServerResponse;
14 | import io.helidon.webserver.Service;
15 | import org.neo4j.driver.v1.Driver;
16 |
17 | import javax.json.Json;
18 | import javax.json.JsonObject;
19 | import java.util.List;
20 | import java.util.logging.Logger;
21 |
22 | public class ParsePackageService implements Service {
23 |
24 | private static final Logger LOGGER = Logger.getLogger(ParsePackageService.class.getName());
25 | /**
26 | * This gets config from application.yaml on classpath
27 | * and uses "app" section.
28 | */
29 | private final Config CONFIG = Config.create().get("app");
30 | private final String rootDir = CONFIG.get("root").asString("~/workspace");
31 | private String neo4jServer = CONFIG.get("neo4j-server").asString("localhost");
32 | private JavaDaoParser daoParser;
33 |
34 | public ParsePackageService(JavaDaoParserFactory javaDaoParserFactory) {
35 | daoParser = javaDaoParserFactory.createDaoParser();
36 | }
37 |
38 | @Override
39 | public void update(Routing.Rules rules) {
40 | rules
41 | .post("/{package}", this::parse);
42 | }
43 |
44 | /**
45 | * Return a wordly greeting message.
46 | * @param request the server request
47 | * @param response the server response
48 | */
49 | private void parse(final ServerRequest request,
50 | final ServerResponse response) {
51 | String pkg = request.path().param("package");
52 |
53 | try {
54 | parse(pkg);
55 | JsonObject returnObject = Json.createObjectBuilder()
56 | .add("message", pkg)
57 | .build();
58 | response.send(returnObject);
59 | } catch (Exception e) {
60 | e.printStackTrace();
61 | JsonObject returnObject = Json.createObjectBuilder()
62 | .add("message", e.getMessage())
63 | .build();
64 | response.send(returnObject);
65 | }
66 |
67 | }
68 |
69 | private void parse(String pkg) throws Exception {
70 | Driver driver = Neo4JDriverFactory.create(neo4jServer);
71 | String dir = String.format("%s/cbs/src/main/java/%s",rootDir,pkg.replaceAll("\\.","/"));
72 | new JavaIdentifierApp(driver).analysisDir(dir);
73 | JavaClassQuery classQuery = new JavaClassQuery(driver);
74 | List clzs = classQuery.load();
75 | JavaCallApp javaCallApp = new JavaCallApp(driver, daoParser);
76 | javaCallApp.analysisDir(dir,clzs);
77 | LOGGER.info("finished and close driver.");
78 | driver.close();
79 | }
80 |
81 | }
82 |
--------------------------------------------------------------------------------
/src/main/java/evolution/analysis/jv/ProcessFiles.java:
--------------------------------------------------------------------------------
1 | package evolution.analysis.jv;
2 |
3 | import java.io.IOException;
4 | import java.nio.file.FileVisitResult;
5 | import java.nio.file.Path;
6 | import java.nio.file.SimpleFileVisitor;
7 | import java.nio.file.attribute.BasicFileAttributes;
8 | import java.util.List;
9 | import java.util.concurrent.ExecutorService;
10 | import java.util.concurrent.Future;
11 | import java.util.function.Consumer;
12 |
13 | import static java.nio.file.FileVisitResult.CONTINUE;
14 |
15 | public class ProcessFiles extends SimpleFileVisitor {
16 |
17 | private final Consumer process;
18 | private final ExecutorService pool;
19 | private final List futures;
20 | public ProcessFiles(Consumer process, ExecutorService pool,List futures) {
21 | this.pool = pool;
22 | this.process = process;
23 | this.futures = futures;
24 | }
25 |
26 | // Print information about
27 | // each type of file.
28 | @Override
29 | public FileVisitResult visitFile(Path file,
30 | BasicFileAttributes attr) {
31 | if (attr.isSymbolicLink()) {
32 | //System.out.format("Symbolic link: %s ", file);
33 | } else if (attr.isRegularFile()) {
34 | // System.out.format("Regular file: %s , name: %s ", file, file.getFileName());
35 | // System.out.format("%s, %s",file.endsWith("java"),file.toString().endsWith(".java"));
36 | // System.out.println("(" + attr.size() + "bytes)");
37 | } else {
38 | //System.out.format("Other: %s ", file);
39 | }
40 |
41 | if (attr.isRegularFile()) {
42 | //System.out.format("Regular file: %s ", file);
43 | //System.out.println("(" + attr.size() + "bytes)");
44 | if (pool != null) {
45 | Future f = pool.submit(() -> process.accept(file));
46 | futures.add(f);
47 | } else {
48 | process.accept(file);
49 | }
50 | }
51 | return CONTINUE;
52 | }
53 |
54 | // Print each directory visited.
55 | @Override
56 | public FileVisitResult postVisitDirectory(Path dir,
57 | IOException exc) {
58 | //System.out.format("Directory: %s%n", dir);
59 | return CONTINUE;
60 | }
61 |
62 | // If there is some error accessing
63 | // the file, let the user know.
64 | // If you don't override this method
65 | // and an error occurs, an IOException
66 | // is thrown.
67 | @Override
68 | public FileVisitResult visitFileFailed(Path file,
69 | IOException exc) {
70 | System.err.println(exc);
71 | return CONTINUE;
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/src/main/java/evolution/analysis/jv/calls/JavaCallApp.java:
--------------------------------------------------------------------------------
1 | package evolution.analysis.jv.calls;
2 |
3 | import evolution.analysis.jv.JavaParserBaseVisitor;
4 | import evolution.analysis.jv.ProcessFiles;
5 | import evolution.analysis.jv.calls.model.JMethodCall;
6 | import evolution.analysis.jv.identifier.JavaFileParser;
7 | import org.antlr.v4.runtime.tree.ParseTree;
8 | import org.neo4j.driver.v1.Driver;
9 |
10 | import java.io.IOException;
11 | import java.nio.file.Files;
12 | import java.nio.file.Path;
13 | import java.nio.file.Paths;
14 | import java.util.ArrayList;
15 | import java.util.List;
16 | import java.util.concurrent.ExecutionException;
17 | import java.util.concurrent.ExecutorService;
18 | import java.util.concurrent.Executors;
19 | import java.util.concurrent.Future;
20 | import java.util.concurrent.atomic.AtomicInteger;
21 | import java.util.function.Consumer;
22 |
23 | public class JavaCallApp {
24 |
25 | private final JavaMethodCallStore store;
26 | private AtomicInteger counter = new AtomicInteger(0);
27 | private JavaDaoParser daoParser;
28 | public JavaCallApp(Driver driver,JavaDaoParser daoParser) {
29 | this.store = new JavaMethodCallStore(driver);
30 | this.daoParser = daoParser;
31 | }
32 |
33 | public void analysisDir(String dir, List clzs) throws IOException, InterruptedException, ExecutionException {
34 | Path startingDir = Paths.get(dir);
35 | Consumer fileAnalysis = parse(clzs);
36 | int poolSize = 8;
37 | ExecutorService pool = Executors.newFixedThreadPool(poolSize);
38 | List futures = new ArrayList<>();
39 | ProcessFiles pf = new ProcessFiles(fileAnalysis,pool,futures);
40 | Files.walkFileTree(startingDir, pf);
41 | for(Future f: futures) {
42 | f.get();
43 | }
44 | pool.shutdown();
45 | }
46 |
47 | private Consumer parse(List clzs) {
48 | return (Path path) -> {
49 | try {
50 | if (!path.toString().endsWith("Tests.java")
51 | && !path.toString().endsWith("Test.java") && path.toString().endsWith(".java")) {
52 | parse(path, clzs);
53 | }
54 | } catch (IOException e) {
55 | e.printStackTrace();
56 | }
57 | };
58 | }
59 |
60 | public void parse(Path path, List clzs) throws IOException {
61 | System.out.println("Start parse java call: " + path.getFileName());
62 | ParseTree tree = JavaFileParser.parse(path);
63 | List calls = new ArrayList<>();
64 | JavaParserBaseVisitor visitor = new JavaCallVisitor(calls,clzs, daoParser);
65 | visitor.visit(tree);
66 | long start = System.currentTimeMillis();
67 | store.save(calls);
68 | long stop = System.currentTimeMillis();
69 | int current = counter.incrementAndGet();
70 | System.out.println(current + ": Save "+path.getFileName().toString()+", Spend Time: " + (stop - start) / 1000 + " s @" + Thread.currentThread().getName());
71 | }
72 |
73 | }
74 |
--------------------------------------------------------------------------------
/src/main/java/evolution/analysis/jv/calls/JavaCallVisitor.java:
--------------------------------------------------------------------------------
1 | package evolution.analysis.jv.calls;
2 |
3 | import evolution.analysis.jv.JavaParser;
4 | import evolution.analysis.jv.JavaParserBaseVisitor;
5 | import evolution.analysis.jv.calls.model.JMethodCall;
6 | import org.antlr.v4.runtime.tree.ParseTree;
7 |
8 | import java.util.ArrayList;
9 | import java.util.HashMap;
10 | import java.util.List;
11 | import java.util.Map;
12 | import java.util.logging.Logger;
13 |
14 | public class JavaCallVisitor extends JavaParserBaseVisitor {
15 |
16 | private static final Logger LOGGER = Logger.getLogger(JavaCallVisitor.class.getName());
17 | private Map fields = new HashMap<>();
18 | private Map formalParameters = new HashMap<>();
19 | private Map localVars = new HashMap<>();
20 | private String currentClz = null;
21 | private String currentPkg = null;
22 | private List imports = new ArrayList<>();
23 | private JavaDaoParser daoParser;
24 |
25 | private final List clzs;
26 | private JMethodCall currentMethodCall;
27 |
28 | private List methodCalls;
29 |
30 | public JavaCallVisitor(List methodCalls,List clzs,JavaDaoParser daoParser) {
31 | this.clzs = clzs;
32 | this.methodCalls = methodCalls;
33 | this.daoParser = daoParser;
34 | }
35 |
36 | @Override
37 | public Object visitPackageDeclaration(evolution.analysis.jv.JavaParser.PackageDeclarationContext ctx) {
38 | currentPkg = ctx.qualifiedName().getText();
39 | return super.visitPackageDeclaration(ctx);
40 | }
41 |
42 | @Override
43 | public Object visitImportDeclaration(evolution.analysis.jv.JavaParser.ImportDeclarationContext ctx) {
44 | imports.add(ctx.qualifiedName().getText());
45 | return super.visitImportDeclaration(ctx);
46 | }
47 |
48 | @Override
49 | public Object visitClassDeclaration(evolution.analysis.jv.JavaParser.ClassDeclarationContext ctx) {
50 | currentClz = ctx.IDENTIFIER().getText();
51 | return super.visitClassDeclaration(ctx);
52 | }
53 |
54 | @Override
55 | public Object visitTypeDeclaration(evolution.analysis.jv.JavaParser.TypeDeclarationContext ctx) {
56 | //System.out.println(ctx.getText());
57 | return super.visitTypeDeclaration(ctx);
58 | }
59 |
60 | @Override public Object visitInterfaceDeclaration(JavaParser.InterfaceDeclarationContext ctx) {
61 | currentClz = ctx.IDENTIFIER().getText();
62 | return super.visitChildren(ctx);
63 | }
64 |
65 | @Override public Object visitInterfaceMethodDeclaration(JavaParser.InterfaceMethodDeclarationContext ctx) {
66 | currentMethodCall = new JMethodCall();
67 | methodCalls.add(currentMethodCall);
68 | currentMethodCall.setPkg(currentPkg);
69 | currentMethodCall.setClz(currentClz);
70 | currentMethodCall.setMethodName(ctx.IDENTIFIER().getText());
71 | daoParser.parse(currentMethodCall,ctx.IDENTIFIER().getText());
72 | return super.visitChildren(ctx);
73 | }
74 |
75 | @Override
76 | public Object visitMethodDeclaration(evolution.analysis.jv.JavaParser.MethodDeclarationContext ctx) {
77 | //System.out.println("\nMethod: " + ctx.IDENTIFIER().getText());
78 | currentMethodCall = new JMethodCall();
79 | methodCalls.add(currentMethodCall);
80 | currentMethodCall.setPkg(currentPkg);
81 | currentMethodCall.setClz(currentClz);
82 | currentMethodCall.setMethodName(ctx.IDENTIFIER().getText());
83 |
84 | String body = ctx.getText().toUpperCase();
85 | daoParser.parse(currentMethodCall,body);
86 |
87 | return super.visitMethodDeclaration(ctx);
88 | }
89 |
90 | @Override
91 | public Object visitMethodCall(evolution.analysis.jv.JavaParser.MethodCallContext ctx) {
92 |
93 | if (currentMethodCall != null) {
94 | String targetType = parseTargetType(ctx);
95 | String callee = ctx.getChild(0).getText();
96 |
97 | String warpTargetFullType = warpTargetFullType(targetType);
98 | if(warpTargetFullType != null) {
99 | currentMethodCall.addMethodCall(warpTargetFullType, callee);
100 | } else {
101 | //System.out.println("Can not wrap:\t" + targetType);
102 | }
103 |
104 | }
105 | return super.visitMethodCall(ctx);
106 | }
107 |
108 | private String warpTargetFullType(String targetType) {
109 | if (currentClz.equalsIgnoreCase(targetType)) {
110 | return currentPkg + "." + targetType;
111 | }
112 | for (String imp : imports) {
113 | if (imp.endsWith(targetType)) {
114 | return imp;
115 | }
116 | }
117 | //maybe the same package
118 | for(String c: clzs) {
119 | if(c.endsWith(targetType)) {
120 | return c;
121 | }
122 | }
123 | //1. current package, 2. import by *
124 | return null;
125 | }
126 |
127 | private String parseTargetType(JavaParser.MethodCallContext ctx) {
128 | ParseTree targetCtx = ctx.getParent().getChild(0);
129 | String targetVar = targetCtx.getText();
130 | String targetType = targetVar;
131 | String parentCtxClz = targetCtx.getClass().getCanonicalName();
132 | if ("me.analysis.jv.JavaParser.MethodCallContext".equals(parentCtxClz)) {
133 | targetType = currentClz;
134 | } else if ("this".equalsIgnoreCase(targetVar)) {
135 | targetType = currentClz;
136 | } else if (targetVar.matches(".*new.*\\)\\..*") && isNotSpecialNewWord(targetVar)) {
137 | try {
138 | targetType = parseNewType(targetCtx);
139 | //System.out.println("Matched: " + targetVar + " , " +targetType);
140 | } catch (NullPointerException e) {
141 | //not create object new method. but name include new word.
142 | LOGGER.info(ctx.getParent().getText());
143 | //System.out.println(currentClz + " . " + currentMethodCall.getMethodName());
144 | //System.out.println(targetCtx.getText());
145 | LOGGER.info(e.getMessage());
146 | }
147 | } else {
148 | String fieldType = fields.get(targetVar);
149 | String formalType = formalParameters.get(targetVar);
150 | String localVarType = localVars.get(targetVar);
151 | if (fieldType != null) {
152 | targetType = fieldType;
153 | } else if (formalType != null) {
154 | targetType = formalType;
155 | } else if (localVarType != null) {
156 | targetType = localVarType;
157 | }
158 | }
159 | return targetType;
160 | }
161 |
162 | private boolean isNotSpecialNewWord(String targetVar) {
163 | return !targetVar.contains("inspectionnew") && !targetVar.contains("renew") && !targetVar.contains("Renew")
164 | && !targetVar.contains("newcoverages") && !targetVar.contains("newCoverages");
165 | }
166 |
167 | private String parseNewType(ParseTree ctx) {
168 | ParseTree creatorCxt = getJavaParserCreatorCxt(ctx);
169 | return creatorCxt.getChild(0).getText();
170 | }
171 |
172 | private ParseTree getJavaParserCreatorCxt(ParseTree ctx) {
173 | if ("me.analysis.jv.JavaParser.CreatorContext".equals(ctx.getClass().getCanonicalName())) {
174 | return ctx;
175 | } else {
176 | ParseTree res = null;
177 | for (int i = 0; i < ctx.getChildCount(); i++) {
178 | ParseTree c = getJavaParserCreatorCxt(ctx.getChild(i));
179 | if (c != null) {
180 | res = c;
181 | break;
182 | }
183 | }
184 | return res;
185 | }
186 | }
187 |
188 | @Override
189 | public Object visitFormalParameters(evolution.analysis.jv.JavaParser.FormalParametersContext ctx) {
190 | //System.out.println(ctx.getText());
191 | return super.visitFormalParameters(ctx);
192 | }
193 |
194 | @Override
195 | public Object visitFormalParameter(evolution.analysis.jv.JavaParser.FormalParameterContext ctx) {
196 | //System.out.println(ctx.typeType().getText() + ":" + ctx.variableDeclaratorId().getText() + "@me.analysis.jv.JavaParser.FormalParameterContext");
197 | formalParameters.put(ctx.variableDeclaratorId().getText(), ctx.typeType().getText());
198 | return super.visitFormalParameter(ctx);
199 | }
200 |
201 | @Override
202 | public Object visitFieldDeclaration(evolution.analysis.jv.JavaParser.FieldDeclarationContext ctx) {
203 | JavaParser.VariableDeclaratorsContext variableDeclaratorsContext = ctx.variableDeclarators();
204 | String variableName = variableDeclaratorsContext.getChild(0).getChild(0).getText();
205 | //System.out.println(ctx.typeType().getText() + ":" + variableName);
206 | fields.put(variableName, ctx.typeType().getText());
207 | return super.visitFieldDeclaration(ctx);
208 | }
209 |
210 | @Override
211 | public Object visitLocalVariableDeclaration(JavaParser.LocalVariableDeclarationContext ctx) {
212 | String typ = ctx.getChild(0).getText();
213 | String variableName = ctx.getChild(1).getChild(0).getChild(0).getText();
214 | localVars.put(variableName, typ);
215 | return super.visitChildren(ctx);
216 | }
217 |
218 | @Override
219 | public Object visitVariableDeclarators(evolution.analysis.jv.JavaParser.VariableDeclaratorsContext ctx) {
220 | return super.visitVariableDeclarators(ctx);
221 | }
222 |
223 | @Override
224 | public Object visitArguments(evolution.analysis.jv.JavaParser.ArgumentsContext ctx) {
225 | //调其他方法的参数
226 | // System.out.println("====");
227 | // System.out.println(ctx.getText()+"@me.analysis.jv.JavaParser.ArgumentsContext");
228 | // System.out.println("====");
229 | return super.visitArguments(ctx);
230 | }
231 |
232 | }
233 |
--------------------------------------------------------------------------------
/src/main/java/evolution/analysis/jv/calls/JavaDaoParser.java:
--------------------------------------------------------------------------------
1 | package evolution.analysis.jv.calls;
2 |
3 | import evolution.analysis.jv.calls.model.JMethodCall;
4 |
5 | public interface JavaDaoParser {
6 | void parse(JMethodCall currentMethodCall, String body);
7 | }
8 |
--------------------------------------------------------------------------------
/src/main/java/evolution/analysis/jv/calls/JavaMethodCallStore.java:
--------------------------------------------------------------------------------
1 | package evolution.analysis.jv.calls;
2 |
3 | import evolution.analysis.jv.calls.model.JMethodCall;
4 | import io.helidon.config.Config;
5 | import org.neo4j.driver.v1.*;
6 |
7 | import java.text.SimpleDateFormat;
8 | import java.util.Date;
9 | import java.util.List;
10 | import java.util.Map;
11 | import java.util.logging.Logger;
12 |
13 | import static org.neo4j.driver.v1.Values.parameters;
14 |
15 | public class JavaMethodCallStore {
16 |
17 | private static final Logger LOGGER = Logger.getLogger(JavaMethodCallStore.class.getName());
18 | private final Config config = Config.create().get("app");
19 | private final List includeKeyWorks = config.get("keywords").asList(String.class);
20 | private Driver driver;
21 |
22 | public JavaMethodCallStore(Driver driver) {
23 | this.driver = driver;
24 | }
25 |
26 | private boolean isIgnoreCallee(String callee) {
27 | //return callee.startsWith("get") || callee.startsWith("set");
28 | return true; //ignore all java callee
29 | }
30 |
31 | private boolean isTargetClass(String clz) {
32 | boolean res = false;
33 | for (String keyword : includeKeyWorks) {
34 | res = res || clz.contains(keyword);
35 | }
36 | return res;
37 | }
38 |
39 | public void save(List methodCalls) {
40 | try (Session session = driver.session()) {
41 | session.writeTransaction(new TransactionWork() {
42 | @Override
43 | public Integer execute(Transaction tx) {
44 | for (JMethodCall ident : methodCalls) {
45 | String pkg = ident.getPkg();
46 | String clz = ident.getClz();
47 | String callerFullName = pkg + "." + clz + "." + ident.getMethodName();
48 | saveCallJavaMethod(tx, ident, callerFullName);
49 | saveAccessTable(tx, ident, callerFullName);
50 | saveCallProcedure(tx, ident, callerFullName);
51 |
52 | }
53 | return methodCalls.size();
54 | }
55 | });
56 | }
57 | }
58 |
59 | private void saveCallProcedure(Transaction tx, JMethodCall ident, String callerFullName) {
60 | for (String pl : ident.getProcedures()) {
61 | tx.run("MATCH (caller:JMethod {fullname: $callerfullname}) " +
62 | "MATCH (callee:PLProcedure {fullname: $calleefullname}) " +
63 | "MERGE (caller)-[:Call {date:$date}]->(callee)",
64 | parameters("callerfullname", callerFullName, "date", getToday(),
65 | "calleefullname", pl));
66 | }
67 | }
68 |
69 | private void saveAccessTable(Transaction tx, JMethodCall ident, String callerFullName) {
70 | for (Map.Entry s : ident.getTableOps().entrySet()) {
71 | String table = s.getKey().toString();
72 | String op = s.getValue().toString();
73 | LOGGER.info("save table: " + table);
74 | tx.run("MATCH (caller:JMethod {fullname: $callerfullname}) " +
75 | "MERGE (t:Table {name: $table}) " +
76 | "MERGE (caller)-[:__op__ {date:$date}]->(t)".replace("__op__", op),
77 | parameters("callerfullname", callerFullName, "date", getToday(),
78 | "table", table));
79 | }
80 | }
81 |
82 | private void saveCallJavaMethod(Transaction tx, JMethodCall ident, String callerFullName) {
83 | for (String calleeClz : ident.getMethodCalls().keySet()) {
84 | if (isTargetClass(calleeClz)) {
85 | //System.out.println("try to save: " + calleeClz);
86 | for (String callee : ident.getMethodCalls().get(calleeClz)) {
87 | if (!isIgnoreCallee(callee)) {
88 | //System.out.println("\t" + callee);
89 | tx.run("MATCH (caller:JMethod {fullname: $callerfullname}) " +
90 | "MATCH (callee:JMethod {fullname: $calleefullname}) " +
91 | "MERGE (caller)-[:Call {date:$date}]->(callee)",
92 | parameters("callerfullname", callerFullName, "date", getToday(),
93 | "calleefullname", calleeClz + "." + callee));
94 | }
95 | }
96 | }
97 | }
98 | }
99 |
100 | private String today = new SimpleDateFormat("yyyy-MM-dd").format(new Date());
101 |
102 | private String getToday() {
103 | return today;
104 | }
105 |
106 | }
107 |
--------------------------------------------------------------------------------
/src/main/java/evolution/analysis/jv/calls/model/JMethodCall.java:
--------------------------------------------------------------------------------
1 | package evolution.analysis.jv.calls.model;
2 |
3 | import java.util.*;
4 |
5 | public class JMethodCall {
6 | private String pkg;
7 | private String clz;
8 | private String methodName;
9 | private Map> methodCalls = new HashMap<>();
10 | private Map tableOps = new HashMap<>();
11 | private Set procedures = new HashSet<>();
12 |
13 | public String getPkg() {
14 | return pkg;
15 | }
16 |
17 | public void setPkg(String pkg) {
18 | this.pkg = pkg;
19 | }
20 |
21 | public String getClz() {
22 | return clz;
23 | }
24 |
25 | public void setClz(String clz) {
26 | this.clz = clz;
27 | }
28 |
29 | public String getMethodName() {
30 | return methodName;
31 | }
32 |
33 | public void setMethodName(String methodName) {
34 | this.methodName = methodName;
35 | }
36 |
37 | public Map> getMethodCalls() {
38 | return methodCalls;
39 | }
40 |
41 | public void addMethodCall(String targetType, String method) {
42 | //System.out.println(targetType+"->"+method);
43 | Set methods = methodCalls.get(targetType);
44 | if(methods == null) {
45 | methods = new HashSet<>();
46 | methodCalls.put(targetType,methods);
47 | }
48 | methods.add(method);
49 | }
50 |
51 | public Set getProcedures() {
52 | return procedures;
53 | }
54 |
55 | public void addProcedures(List procedures) {
56 | for(String p:procedures) {
57 | this.procedures.add(p.toUpperCase());
58 | }
59 | }
60 |
61 | public Map getTableOps() {
62 | return tableOps;
63 | }
64 |
65 | public void addTableOps(Map tableOps) {
66 | this.tableOps.putAll(tableOps);
67 | }
68 |
69 | public void addTableOp(String table,String op) {
70 | this.tableOps.put(table,op.toUpperCase());
71 | }
72 |
73 | @Override
74 | public String toString() {
75 | return "JMethodCall{" +
76 | "pkg='" + pkg + '\'' +
77 | ", clz='" + clz + '\'' +
78 | ", methodName='" + methodName + '\'' +
79 | ", methodCalls=" + methodCalls +
80 | ", tableOps=" + tableOps +
81 | '}';
82 | }
83 | }
84 |
--------------------------------------------------------------------------------
/src/main/java/evolution/analysis/jv/calls/plugins/JavaDaoStringParser.java:
--------------------------------------------------------------------------------
1 | package evolution.analysis.jv.calls.plugins;
2 |
3 | import evolution.analysis.jv.calls.JavaDaoParser;
4 | import evolution.analysis.jv.calls.model.JMethodCall;
5 |
6 | import java.util.*;
7 | import java.util.logging.Logger;
8 | import java.util.regex.Matcher;
9 | import java.util.regex.Pattern;
10 |
11 | public class JavaDaoStringParser implements JavaDaoParser {
12 | private static final Logger LOGGER = Logger.getLogger(JavaDaoStringParser.class.getName());
13 |
14 | @Override
15 | public void parse(JMethodCall currentMethod, String body) {
16 | if (!isContainTable(body)) {
17 | return;
18 | }
19 | Map tableOpsMap = buildTableOps(body);
20 | currentMethod.addTableOps(tableOpsMap);
21 | LOGGER.info(currentMethod.getMethodName() + " use table size: " + currentMethod.getTableOps().size());
22 | List procedures = parseProcedureCalls(body);
23 | currentMethod.addProcedures(procedures);
24 |
25 | }
26 |
27 | private boolean isContainTable(String body) {
28 | return body.contains("T_") || body.contains("CALL");
29 | }
30 |
31 |
32 | protected List parseProcedureCalls(String body) {
33 | ArrayList res = new ArrayList<>();
34 | String s = "(?:\\{.?(call|select|SELECT|CALL)\\s+)([a-zA-Z_\\d]+\\.[a-zA-Z_\\d]+)\\(";
35 | final Pattern p = Pattern.compile(s);
36 | final Matcher m = p.matcher(body);
37 | while (m.find()) {
38 | String pl = m.group(2);
39 | res.add(pl);
40 | }
41 | return res;
42 | }
43 |
44 |
45 | private Map buildTableOps(String body) {
46 | Map tableOpsMap = new HashMap<>();
47 | List tableOps = parseTables(body);
48 | LOGGER.info("buildTableOps: " + tableOps.toString());
49 | if (tableOps == null || tableOps.size() == 0) {
50 | return tableOpsMap;
51 | }
52 |
53 | String op = tableOps.get(0);
54 | if (!isTableOperator(op)) {
55 | LOGGER.warning(body);
56 | }
57 | LOGGER.info("tableOps.size: " + tableOps.size());
58 | for (int i = 1; i < tableOps.size(); i++) {
59 | String s = tableOps.get(i);
60 | if (isTableOperator(s)) {
61 | op = s;
62 | } else {
63 | tableOpsMap.put(cleanTableName(s.toUpperCase()), op);
64 | }
65 | }
66 |
67 | return tableOpsMap;
68 | }
69 |
70 |
71 | public String cleanTableName(String table) {
72 | String pattern = "([A-Z_]+).*";
73 | Pattern r = Pattern.compile(pattern);
74 | Matcher matcher = r.matcher(table);
75 | matcher.find();
76 | return matcher.group(1);
77 | }
78 |
79 |
80 | private boolean isTableOperator(String s) {
81 | return "INSERT".equalsIgnoreCase(s)
82 | || "SELECT".equalsIgnoreCase(s)
83 | || "UPDATE".equalsIgnoreCase(s)
84 | || "DELETE".equalsIgnoreCase(s);
85 | }
86 |
87 | protected List parseTables(String body) {
88 | List result = new ArrayList<>();
89 | String[] ts = body.split("[\\s{2,}|\"|,]");
90 | Object[] ss = Arrays.stream(ts).filter(s -> !s.trim().isEmpty()).toArray();
91 |
92 | for (int i = 0; i < ss.length - 1; i++) {
93 | String s = ss[i].toString();
94 | if (s.startsWith("t_") || s.startsWith("T_") || s.startsWith("vdm_") || s.startsWith("VDM_")) {
95 | //select from, insert into,delete from,update
96 | String op = parseTableOperate(ss, i);
97 | if (op != null) {
98 | result.add(op);
99 | }
100 | result.add(s);
101 | }
102 | }
103 | return result;
104 | }
105 |
106 | private String parseTableOperate(Object[] ts, int index) {
107 | String pre = ts[index - 1].toString();
108 | while (!("from".equalsIgnoreCase(pre.trim()) || isTableOperator(pre)) && index > 0) {
109 | index = index - 1;
110 | pre = ts[index - 1].toString();
111 | }
112 | String op = null;
113 | if ("update".equalsIgnoreCase(pre)) {
114 | op = "UPDATE";
115 | } else if ("into".equalsIgnoreCase(pre)) {
116 | op = "INSERT";
117 | } else if ("from".equalsIgnoreCase(pre)) {
118 | String prePre = ts[index - 2].toString();
119 | if ("delete".equalsIgnoreCase(prePre)) {
120 | op = "DELETE";
121 | } else {
122 | op = "SELECT";
123 | }
124 | } else if ("delete".equalsIgnoreCase(pre)) {
125 | op = "DELETE";
126 | }
127 | return op;
128 | }
129 |
130 | }
131 |
--------------------------------------------------------------------------------
/src/main/java/evolution/analysis/jv/calls/plugins/MyBatisParser.java:
--------------------------------------------------------------------------------
1 | package evolution.analysis.jv.calls.plugins;
2 |
3 | import evolution.analysis.jv.calls.JavaDaoParser;
4 | import evolution.analysis.jv.calls.model.JMethodCall;
5 |
6 | import evolution.analysis.jv.calls.plugins.sql.TableOpParser;
7 | import evolution.analysis.jv.calls.plugins.sql.TableVisitor;
8 | import org.antlr.v4.runtime.tree.ParseTree;
9 | import org.w3c.dom.*;
10 | import org.xml.sax.SAXException;
11 |
12 | import javax.xml.parsers.*;
13 | import java.io.*;
14 |
15 | import java.nio.file.Files;
16 | import java.nio.file.Paths;
17 | import java.util.HashMap;
18 | import java.util.Map;
19 | import java.util.logging.Logger;
20 |
21 | public class MyBatisParser implements JavaDaoParser {
22 |
23 | private static final Logger LOGGER = Logger.getLogger(MyBatisParser.class.getName());
24 |
25 | private String rootDir;
26 | public MyBatisParser(String rootDir) {
27 | this.rootDir = rootDir;
28 | }
29 | @Override
30 | public void parse(JMethodCall currentMethod, String body) {
31 | String pkg = currentMethod.getPkg();
32 | String clz = currentMethod.getClz();
33 | String clzFullName = pkg + "." + clz;
34 | String file = String.format("%s/src/main/resources/%s.xml",rootDir,clzFullName.replaceAll("\\.","/"));
35 | if(!(clzFullName.toLowerCase().contains("mapper") || clzFullName.toLowerCase().contains("dao"))
36 | || !Files.exists(Paths.get(file))){
37 | return;
38 | }
39 | String sql = "";
40 | try {
41 | sql = findMethodSql(file,currentMethod.getMethodName());
42 |
43 | System.out.println(currentMethod.getMethodName());
44 | //System.out.println(sql.trim());
45 | Map tableOpsMap = parse(replaceVariable(sql.trim()));
46 | System.out.println(tableOpsMap);
47 | currentMethod.addTableOps(tableOpsMap);
48 | } catch (ParserConfigurationException e) {
49 | e.printStackTrace();
50 | } catch (IOException e) {
51 | e.printStackTrace();
52 | } catch (SAXException e) {
53 | e.printStackTrace();
54 | }
55 | }
56 |
57 | private Map parse(String sql) throws IOException {
58 | Map tableOpsMap = new HashMap<>();
59 | TableOpParser parser = new TableOpParser();
60 | ParseTree tree = parser.parse(sql);
61 | tree.accept(new TableVisitor(tableOpsMap));
62 | return tableOpsMap;
63 | }
64 |
65 | private String replaceVariable(String sql) {
66 | return sql.replaceAll("#\\{","").replaceAll("\\}","");
67 | }
68 |
69 | private String findMethodSql(String path, String method) throws ParserConfigurationException, IOException, SAXException {
70 | File inputFile = new File(path);
71 | //parse mapper xml
72 | DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
73 | DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
74 | Document doc = dBuilder.parse(inputFile);
75 | doc.getDocumentElement().normalize();
76 | //find method
77 |
78 | NodeList nList = doc.getDocumentElement().getChildNodes();
79 | for (int temp = 0; temp < nList.getLength(); temp++) {
80 | Node nNode = nList.item(temp);
81 | if(nNode.getAttributes() != null && nNode.getAttributes().getNamedItem("id") != null) {
82 | String id = nNode.getAttributes().getNamedItem("id").getNodeValue();
83 | if (method.equalsIgnoreCase(id)) {
84 | //extract sql string
85 | String sql = nNode.getLastChild().getNodeValue();
86 | return sql;
87 | }
88 | }
89 | }
90 | return "";
91 | }
92 | }
93 |
--------------------------------------------------------------------------------
/src/main/java/evolution/analysis/jv/calls/plugins/sql/TableOpParser.java:
--------------------------------------------------------------------------------
1 | package evolution.analysis.jv.calls.plugins.sql;
2 |
3 | import evolution.analysis.sql.SqlLexer;
4 | import evolution.analysis.sql.SqlParser;
5 | import org.antlr.v4.runtime.CharStream;
6 | import org.antlr.v4.runtime.CharStreams;
7 | import org.antlr.v4.runtime.CommonTokenStream;
8 | import org.antlr.v4.runtime.tree.ParseTree;
9 |
10 | import java.io.IOException;
11 |
12 |
13 | public class TableOpParser {
14 |
15 | public ParseTree parse(String sql) throws IOException {
16 | CharStream stream = CharStreams.fromString(sql);
17 | SqlLexer lexer = new SqlLexer(stream);
18 | CommonTokenStream tokens = new CommonTokenStream( lexer );
19 | SqlParser parser = new SqlParser(tokens);
20 | return parser.parse();
21 | }
22 |
23 | }
24 |
--------------------------------------------------------------------------------
/src/main/java/evolution/analysis/jv/calls/plugins/sql/TableVisitor.java:
--------------------------------------------------------------------------------
1 | package evolution.analysis.jv.calls.plugins.sql;
2 |
3 |
4 | import evolution.analysis.sql.SqlBaseVisitor;
5 | import evolution.analysis.sql.SqlParser;
6 | import org.antlr.v4.runtime.tree.ParseTree;
7 |
8 | import java.util.Map;
9 |
10 | public class TableVisitor extends SqlBaseVisitor {
11 |
12 | private Map tableOps;
13 | public TableVisitor(Map tableOps) {
14 | this.tableOps = tableOps;
15 | }
16 |
17 |
18 | @Override
19 | public Void visitSelect_stmt(SqlParser.Select_stmtContext ctx) {
20 | System.out.println("SELECT: " + ctx.getText());
21 | return super.visitChildren(ctx);
22 | }
23 |
24 | @Override
25 | public Void visitSimple_select_stmt(SqlParser.Simple_select_stmtContext ctx) {
26 | System.out.printf("visitSimple_select SELECT: %s%n", ctx.getText());
27 | return super.visitChildren(ctx);
28 | }
29 |
30 | @Override
31 | public Void visitSelect_or_values(SqlParser.Select_or_valuesContext ctx) {
32 | System.out.printf("visitSelect_or_values SELECT: %s%n", ctx.getText());
33 | return super.visitChildren(ctx);
34 | }
35 |
36 | @Override
37 | public Void visitTable_or_subquery(SqlParser.Table_or_subqueryContext ctx) {
38 | ParseTree child = ctx.getChild(0);
39 | if(child instanceof evolution.analysis.sql.SqlParser.Table_nameContext) {
40 | tableOps.put(child.getText(),"SELECT");
41 | } else {
42 | //System.out.printf("visitTable_or_subquery SELECT: %s @%s \n", ctx.getText(), child.getClass().getCanonicalName());
43 | }
44 | return super.visitChildren(ctx);
45 | }
46 |
47 | @Override
48 | public Void visitSelect_core(SqlParser.Select_coreContext ctx) {
49 | //System.out.printf("visitSelect_core SELECT: %s%n", ctx.getText());
50 | return super.visitChildren(ctx);
51 | }
52 |
53 | @Override
54 | public Void visitCompound_select_stmt(SqlParser.Compound_select_stmtContext ctx) {
55 | System.out.printf("visitCompound_select_stmt SELECT: %s%n", ctx.getText());
56 | return super.visitChildren(ctx);
57 | }
58 |
59 | @Override
60 | public Void visitFactored_select_stmt(SqlParser.Factored_select_stmtContext ctx) {
61 | //System.out.printf("visitFactored_select_stmt SELECT: %s%n", ctx.getText());
62 | return super.visitChildren(ctx);
63 | }
64 |
65 | @Override
66 | public Void visitUpdate_stmt(SqlParser.Update_stmtContext ctx) {
67 | //System.out.println("UPDATE: " + ctx.getText());
68 | tableOps.put(ctx.getChild(1).getText(),"UPDATE");
69 | return super.visitChildren(ctx);
70 | }
71 |
72 | @Override
73 | public Void visitDelete_stmt(SqlParser.Delete_stmtContext ctx) {
74 | System.out.println("DELETE: " + ctx.getText());
75 | tableOps.put(ctx.getChild(2).getText(),"DELETE");
76 | return super.visitChildren(ctx);
77 | }
78 |
79 | @Override
80 | public Void visitInsert_stmt(SqlParser.Insert_stmtContext ctx) {
81 | //System.out.println("INSERT: " + ctx.getText());
82 | tableOps.put(ctx.getChild(2).getText(),"INSERT");
83 | return super.visitChildren(ctx);
84 | }
85 | }
86 |
--------------------------------------------------------------------------------
/src/main/java/evolution/analysis/jv/identifier/JIdentifier.java:
--------------------------------------------------------------------------------
1 | package evolution.analysis.jv.identifier;
2 |
3 | import java.util.ArrayList;
4 | import java.util.List;
5 |
6 | public class JIdentifier {
7 |
8 | private String pkg;
9 | private String name;
10 | private String typ;
11 |
12 | private List methods = new ArrayList<>();
13 |
14 | public String getPkg() {
15 | return pkg;
16 | }
17 |
18 | public String getName() {
19 | return name;
20 | }
21 |
22 |
23 | public List getMethods() {
24 | return methods;
25 | }
26 |
27 | public void setPkg(String pkg) {
28 | this.pkg = pkg;
29 | }
30 |
31 | public void setName(String interfaceName) {
32 | this.name = interfaceName;
33 | }
34 |
35 | public void addMethod(JMethod method) {
36 | this.methods.add(method);
37 | }
38 |
39 | public String getType() {
40 | return typ;
41 | }
42 |
43 | public void setType(String typ) {
44 | this.typ = typ;
45 | }
46 |
47 | @Override
48 | public String toString() {
49 | return "JIdentifier{" +
50 | "pkg='" + pkg + '\'' +
51 | ", name='" + name + '\'' +
52 | ", methods=" + methods +
53 | '}';
54 | }
55 |
56 | }
57 |
--------------------------------------------------------------------------------
/src/main/java/evolution/analysis/jv/identifier/JMethod.java:
--------------------------------------------------------------------------------
1 | package evolution.analysis.jv.identifier;
2 |
3 | public class JMethod {
4 |
5 | private String name;
6 | private int startLine;
7 | private int startLinePosition;
8 | private int stopLine;
9 | private int stopLinePosition;
10 |
11 | public String getName() {
12 | return name;
13 | }
14 |
15 | public void setName(String name) {
16 | this.name = name;
17 | }
18 |
19 | public int getStartLine() {
20 | return startLine;
21 | }
22 |
23 | public void setStartLine(int startLine) {
24 | this.startLine = startLine;
25 | }
26 |
27 | public int getStartLinePosition() {
28 | return startLinePosition;
29 | }
30 |
31 | public void setStartLinePosition(int startLinePosition) {
32 | this.startLinePosition = startLinePosition;
33 | }
34 |
35 | public int getStopLine() {
36 | return stopLine;
37 | }
38 |
39 | public void setStopLine(int stopLine) {
40 | this.stopLine = stopLine;
41 | }
42 |
43 | public int getStopLinePosition() {
44 | return stopLinePosition;
45 | }
46 |
47 | public void setStopLinePosition(int stopLinePosition) {
48 | this.stopLinePosition = stopLinePosition;
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/src/main/java/evolution/analysis/jv/identifier/JavaClassQuery.java:
--------------------------------------------------------------------------------
1 | package evolution.analysis.jv.identifier;
2 |
3 | import org.neo4j.driver.v1.*;
4 |
5 | import java.util.ArrayList;
6 | import java.util.List;
7 |
8 | public class JavaClassQuery {
9 |
10 | private Driver driver;
11 |
12 | public JavaClassQuery(Driver driver) {
13 | this.driver = driver;
14 | }
15 |
16 | public List load() {
17 | try(Session session = driver.session()) {
18 | return session.readTransaction(new TransactionWork>() {
19 | @Override
20 | public List execute(Transaction tx) {
21 | StatementResult res = tx.run("MATCH (c:Class) RETURN c");
22 | List clzs = new ArrayList<>();
23 | while(res.hasNext()) {
24 | Value c1 = res.next().get("c");
25 | String c = c1.get("fullname").asString();
26 | clzs.add(c);
27 | }
28 | return clzs;
29 | }
30 | });
31 | }
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/src/main/java/evolution/analysis/jv/identifier/JavaFileParser.java:
--------------------------------------------------------------------------------
1 | package evolution.analysis.jv.identifier;
2 |
3 | import evolution.analysis.jv.JavaLexer;
4 | import evolution.analysis.jv.JavaParser;
5 | import org.antlr.v4.runtime.CharStream;
6 | import org.antlr.v4.runtime.CharStreams;
7 | import org.antlr.v4.runtime.CommonTokenStream;
8 | import org.antlr.v4.runtime.tree.ParseTree;
9 |
10 | import java.io.IOException;
11 | import java.nio.file.Path;
12 |
13 | public class JavaFileParser {
14 |
15 | public static ParseTree parse(Path path) throws IOException {
16 | CharStream stream = CharStreams.fromPath(path);
17 | JavaLexer lexer = new JavaLexer(stream);
18 | CommonTokenStream tokens = new CommonTokenStream( lexer );
19 | JavaParser parser = new JavaParser(tokens);
20 |
21 | return parser.compilationUnit();
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/src/main/java/evolution/analysis/jv/identifier/JavaIdentifierApp.java:
--------------------------------------------------------------------------------
1 | package evolution.analysis.jv.identifier;
2 |
3 |
4 | import evolution.analysis.jv.JavaParserBaseVisitor;
5 | import evolution.analysis.jv.ProcessFiles;
6 | import org.antlr.v4.runtime.tree.ParseTree;
7 | import org.neo4j.driver.v1.Driver;
8 |
9 | import java.io.IOException;
10 | import java.nio.file.Files;
11 | import java.nio.file.Path;
12 | import java.nio.file.Paths;
13 | import java.util.ArrayList;
14 | import java.util.List;
15 | import java.util.concurrent.ExecutionException;
16 | import java.util.concurrent.ExecutorService;
17 | import java.util.concurrent.Executors;
18 | import java.util.concurrent.Future;
19 |
20 | public class JavaIdentifierApp {
21 |
22 | private final JavaIdentifierStore identStore;
23 | public JavaIdentifierApp(Driver driver) {
24 | this.identStore = new JavaIdentifierStore(driver);
25 | }
26 |
27 | public void analysisDir(String dir) throws IOException, InterruptedException, ExecutionException {
28 | Path startingDir = Paths.get(dir);
29 | int poolSize = 8;
30 | ExecutorService pool = Executors.newFixedThreadPool(poolSize);
31 | List futures = new ArrayList<>();
32 | ProcessFiles pf = new ProcessFiles(this::parse, pool,futures);
33 | Files.walkFileTree(startingDir, pf);
34 | for(Future f: futures) {
35 | f.get();
36 | }
37 | pool.shutdown();
38 | }
39 |
40 | public void parse(Path path) {
41 | try {
42 |
43 | if (!path.toString().endsWith("Tests.java")
44 | && !path.toString().endsWith("Test.java") && path.toString().endsWith(".java")) {
45 | ParseTree tree = JavaFileParser.parse(path);
46 | JIdentifier interfaceIdent = new JIdentifier();
47 | JavaParserBaseVisitor interfaceVisitor = new JavaIdentifierVisitor(interfaceIdent);
48 | interfaceVisitor.visit(tree);
49 | if (interfaceIdent.getName() != null && interfaceIdent.getName() != "") {
50 | identStore.save(interfaceIdent);
51 | }
52 | }
53 | } catch (IOException e) {
54 | e.printStackTrace();
55 | }
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/src/main/java/evolution/analysis/jv/identifier/JavaIdentifierStore.java:
--------------------------------------------------------------------------------
1 | package evolution.analysis.jv.identifier;
2 |
3 | import org.neo4j.driver.v1.Driver;
4 | import org.neo4j.driver.v1.Session;
5 | import org.neo4j.driver.v1.Transaction;
6 | import org.neo4j.driver.v1.TransactionWork;
7 |
8 | import java.text.SimpleDateFormat;
9 | import java.util.Date;
10 | import java.util.logging.Logger;
11 |
12 | import static org.neo4j.driver.v1.Values.parameters;
13 |
14 | public class JavaIdentifierStore {
15 | private static final Logger LOGGER = Logger.getLogger(JavaIdentifierStore.class.getName());
16 | private Driver driver;
17 |
18 | public JavaIdentifierStore(Driver driver) {
19 | this.driver = driver;
20 | }
21 |
22 | public void save(JIdentifier ident) {
23 | System.out.println(ident);
24 | try(Session session = driver.session()) {
25 | session.writeTransaction(new TransactionWork() {
26 | @Override
27 | public Integer execute(Transaction tx) {
28 | String pkg = ident.getPkg();
29 | String clz = ident.getName();
30 | tx.run("MERGE (p:Package {name: $pkg}) " +
31 | "MERGE (c:__typ__ {name: $clz, fullname: $clzFullname}) ".replace("__typ__",ident.getType()) +
32 | "MERGE (p)-[:Has]->(c)",
33 | parameters("pkg", ident.getPkg(),
34 | "clz", clz, "clzFullname", pkg + "." + clz));
35 | LOGGER.info(clz);
36 | for (JMethod m : ident.getMethods()) {
37 | String mFullName = pkg + "." + clz + "." + m.getName();
38 | LOGGER.info("\t"+m.getName());
39 | tx.run("MATCH (c {fullname: $clzFullname}) \n" +
40 | "MERGE (m:JMethod {name: $name, fullname: $fullname,date:$date," +
41 | "startline: $startline, startlinePos: $startlinePos," +
42 | "stopline: $stopline, stoplinePos: $stoplinePos}) " +
43 | "MERGE (c)-[:Has]->(m)",
44 | parameters("clzFullname", pkg + "." + clz,
45 | "name", m.getName(), "fullname", mFullName,"date",getToday(),
46 | "startline",m.getStartLine(),"startlinePos",m.getStartLinePosition(),
47 | "stopline",m.getStopLine(),"stoplinePos",m.getStopLinePosition()));
48 | }
49 | return ident.getMethods().size();
50 | }
51 | });
52 | }
53 | }
54 | private String getToday() {
55 | return new SimpleDateFormat("yyyy-MM-dd").format(new Date());
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/src/main/java/evolution/analysis/jv/identifier/JavaIdentifierVisitor.java:
--------------------------------------------------------------------------------
1 | package evolution.analysis.jv.identifier;
2 |
3 | import evolution.analysis.jv.JavaParser;
4 | import evolution.analysis.jv.JavaParserBaseVisitor;
5 |
6 | public class JavaIdentifierVisitor extends JavaParserBaseVisitor {
7 |
8 | private JIdentifier node;
9 | public JavaIdentifierVisitor(JIdentifier node){
10 | this.node = node;
11 | }
12 |
13 | @Override
14 | public Object visitPackageDeclaration(evolution.analysis.jv.JavaParser.PackageDeclarationContext ctx) {
15 | node.setPkg(ctx.qualifiedName().getText());
16 | return super.visitPackageDeclaration(ctx);
17 | }
18 |
19 |
20 | @Override
21 | public Object visitClassDeclaration(evolution.analysis.jv.JavaParser.ClassDeclarationContext ctx) {
22 | node.setType("Class");
23 | node.setName(ctx.IDENTIFIER().getText());
24 | //XXX: implement interface
25 | return super.visitClassDeclaration(ctx);
26 | }
27 |
28 | @Override
29 | public Object visitMethodDeclaration(evolution.analysis.jv.JavaParser.MethodDeclarationContext ctx) {
30 | JMethod method = new JMethod();
31 | //XXX: find the start position of {, not public
32 | method.setStartLine(ctx.start.getLine());
33 | method.setStartLinePosition(ctx.start.getCharPositionInLine());
34 | method.setStopLine(ctx.stop.getLine());
35 | method.setStopLinePosition(ctx.stop.getCharPositionInLine());
36 | method.setName(ctx.IDENTIFIER().getText());
37 | node.addMethod(method);
38 | return super.visitMethodDeclaration(ctx);
39 | }
40 |
41 | @Override
42 | public Object visitInterfaceDeclaration(JavaParser.InterfaceDeclarationContext ctx) {
43 | node.setType("Interface");
44 | node.setName(ctx.IDENTIFIER().getText());
45 | return super.visitInterfaceDeclaration(ctx);
46 | }
47 |
48 | @Override
49 | public Object visitInterfaceMethodDeclaration(JavaParser.InterfaceMethodDeclarationContext ctx) {
50 | JMethod method = new JMethod();
51 | //XXX: find the start position of {, not public
52 | method.setStartLine(ctx.start.getLine());
53 | method.setStartLinePosition(ctx.start.getCharPositionInLine());
54 | method.setStopLine(ctx.stop.getLine());
55 | method.setStopLinePosition(ctx.stop.getCharPositionInLine());
56 | method.setName(ctx.IDENTIFIER().getText());
57 | node.addMethod(method);
58 | return super.visitInterfaceMethodDeclaration(ctx);
59 | }
60 |
61 | }
62 |
--------------------------------------------------------------------------------
/src/main/java/evolution/configuration/ConfigReader.java:
--------------------------------------------------------------------------------
1 | package evolution.configuration;
2 |
3 | import evolution.factory.daoparser.DaoParserTypeEnum;
4 | import evolution.factory.daoparser.DaoParserProvider;
5 | import io.helidon.config.Config;
6 |
7 | public class ConfigReader implements DaoParserProvider {
8 | private final Config CONFIG = Config.create().get("app");
9 | @Override
10 | public DaoParserTypeEnum getDaoParserType() {
11 | String daoParseType = CONFIG.get("dao-parse-type").asString();
12 | return DaoParserTypeEnum.valueOf(daoParseType);
13 | }
14 |
15 |
16 | @Override
17 | public String getDaoParseRootPath() {
18 | return CONFIG.get("root").asString("~/workspace");
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/src/main/java/evolution/factory/ServiceFactory.java:
--------------------------------------------------------------------------------
1 | package evolution.factory;
2 |
3 | import evolution.analysis.jv.ParseClassService;
4 | import evolution.analysis.jv.ParsePackageService;
5 | import evolution.factory.daoparser.DaoParserProvider;
6 | import evolution.factory.daoparser.JavaDaoParserFactory;
7 |
8 | public class ServiceFactory {
9 | private JavaDaoParserFactory javaDaoParserFactory;
10 |
11 | public ServiceFactory(DaoParserProvider provider) {
12 | javaDaoParserFactory = new JavaDaoParserFactory(provider);
13 | }
14 |
15 | public ParsePackageService createParsePackageService() {
16 | return new ParsePackageService(javaDaoParserFactory);
17 | }
18 |
19 | public ParseClassService createParseClassService() {
20 | return new ParseClassService(javaDaoParserFactory);
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/src/main/java/evolution/factory/daoparser/DaoParserProvider.java:
--------------------------------------------------------------------------------
1 | package evolution.factory.daoparser;
2 |
3 | import evolution.factory.daoparser.DaoParserTypeEnum;
4 |
5 | public interface DaoParserProvider {
6 | DaoParserTypeEnum getDaoParserType();
7 |
8 | String getDaoParseRootPath();
9 | }
10 |
--------------------------------------------------------------------------------
/src/main/java/evolution/factory/daoparser/DaoParserTypeEnum.java:
--------------------------------------------------------------------------------
1 | package evolution.factory.daoparser;
2 |
3 | public enum DaoParserTypeEnum {
4 | MyBatisParser,
5 | StringParser
6 | }
7 |
--------------------------------------------------------------------------------
/src/main/java/evolution/factory/daoparser/JavaDaoParserFactory.java:
--------------------------------------------------------------------------------
1 | package evolution.factory.daoparser;
2 |
3 | import evolution.analysis.jv.calls.JavaDaoParser;
4 | import evolution.analysis.jv.calls.plugins.JavaDaoStringParser;
5 | import evolution.analysis.jv.calls.plugins.MyBatisParser;
6 |
7 | public class JavaDaoParserFactory {
8 |
9 | private final DaoParserProvider provider;
10 |
11 | public JavaDaoParserFactory(DaoParserProvider provider) {
12 | this.provider = provider;
13 | }
14 |
15 | public JavaDaoParser createDaoParser() {
16 | DaoParserTypeEnum daoParserType = this.provider.getDaoParserType();
17 | if(daoParserType == DaoParserTypeEnum.StringParser) {
18 | return new JavaDaoStringParser();
19 | }
20 | if(daoParserType == DaoParserTypeEnum.MyBatisParser) {
21 | return new MyBatisParser(this.provider.getDaoParseRootPath());
22 | }
23 | throw new OutOfJavaDaoParserEnumError(daoParserType);
24 | }
25 |
26 | }
27 |
--------------------------------------------------------------------------------
/src/main/java/evolution/factory/daoparser/OutOfJavaDaoParserEnumError.java:
--------------------------------------------------------------------------------
1 | package evolution.factory.daoparser;
2 |
3 | class OutOfJavaDaoParserEnumError extends Error {
4 | OutOfJavaDaoParserEnumError(DaoParserTypeEnum daoParserType) {
5 | super(String.format("the type %s is out of range", daoParserType.toString()));
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/src/main/java/evolution/store/HelloWorldExample.java:
--------------------------------------------------------------------------------
1 | package evolution.store;
2 |
3 | import org.neo4j.driver.v1.*;
4 |
5 | import static org.neo4j.driver.v1.Values.parameters;
6 |
7 | public class HelloWorldExample implements AutoCloseable {
8 | private final Driver driver;
9 |
10 | public HelloWorldExample(String uri, String user, String password) {
11 | driver = GraphDatabase.driver(uri, AuthTokens.basic(user, password));
12 | }
13 |
14 | @Override
15 | public void close() throws Exception {
16 | driver.close();
17 | }
18 |
19 | public void printGreeting(final String message) {
20 | try (Session session = driver.session()) {
21 | System.out.println(isActorExist(session,"Tom Hanks"));
22 |
23 | String greeting = session.writeTransaction(new TransactionWork() {
24 | @Override
25 | public String execute(Transaction tx) {
26 | StatementResult result = tx.run("CREATE (a:Greeting) " +
27 | "SET a.message = $message " +
28 | "RETURN a.message + ', from node ' + id(a)",
29 | parameters("message", message));
30 |
31 | return result.single().get(0).asString();
32 | }
33 | });
34 | System.out.println(greeting);
35 | }
36 | }
37 |
38 | public boolean isActorExist(Session session, String name) {
39 | return session.readTransaction(new TransactionWork() {
40 | @Override
41 | public Boolean execute(Transaction tx) {
42 | StatementResult result = tx.run("MATCH (a {name: $name}) RETURN a", parameters("name",name));
43 | //Node node = result.single().get(0).asNode();
44 | //System.out.println(node.asMap());
45 | return result.hasNext();
46 | }
47 | });
48 | }
49 |
50 | public static void main(String... args) throws Exception {
51 | try (HelloWorldExample greeter = new HelloWorldExample("bolt://localhost:7687", "xuefeng", "xuefeng")) {
52 | greeter.printGreeting("hello, world");
53 | }
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/src/main/java/evolution/store/Neo4JDriverFactory.java:
--------------------------------------------------------------------------------
1 | package evolution.store;
2 |
3 | import org.neo4j.driver.v1.AuthTokens;
4 | import org.neo4j.driver.v1.Driver;
5 | import org.neo4j.driver.v1.GraphDatabase;
6 |
7 | public class Neo4JDriverFactory {
8 |
9 | public static Driver create(String neo4jServer){
10 | String uri = String.format("bolt://%s:7687",neo4jServer);
11 | String user = "neo4j";
12 | String password = "admin";
13 |
14 | return GraphDatabase.driver(uri, AuthTokens.basic(user, password));
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/src/main/java/evolution/store/StoreManager.java:
--------------------------------------------------------------------------------
1 | package evolution.store;
2 |
3 | import org.neo4j.driver.v1.Driver;
4 | import org.neo4j.driver.v1.Session;
5 | import org.neo4j.driver.v1.Transaction;
6 | import org.neo4j.driver.v1.TransactionWork;
7 |
8 | public class StoreManager {
9 | private final Driver driver;
10 |
11 | public StoreManager(Driver driver) {
12 | this.driver = driver;
13 | }
14 |
15 | public void update(String state) {
16 | try (Session session = driver.session()) {
17 | session.writeTransaction(new TransactionWork() {
18 | @Override
19 | public Integer execute(Transaction tx) {
20 | tx.run(state);
21 | return 0;
22 | }
23 | });
24 | }
25 | }
26 |
27 | }
28 |
--------------------------------------------------------------------------------
/src/main/resources/application.yaml:
--------------------------------------------------------------------------------
1 | #
2 | # Copyright (c) 2018 Oracle and/or its affiliates. All rights reserved.
3 | #
4 | # Licensed under the Apache License, Version 2.0 (the "License");
5 | # you may not use this file except in compliance with the License.
6 | # You may obtain a copy of the License at
7 | #
8 | # http://www.apache.org/licenses/LICENSE-2.0
9 | #
10 | # Unless required by applicable law or agreed to in writing, software
11 | # distributed under the License is distributed on an "AS IS" BASIS,
12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | # See the License for the specific language governing permissions and
14 | # limitations under the License.
15 | #
16 |
17 | app:
18 | greeting: "Hello"
19 | root: "/workspace"
20 | keywords:
21 | - com
22 | neo4j-server: "neo4j"
23 | dao-parse-type: "MyBatisParser"
24 |
25 | server:
26 | port: 8080
27 | host: 0.0.0.0
28 |
--------------------------------------------------------------------------------
/src/main/resources/logging.properties:
--------------------------------------------------------------------------------
1 | #
2 | # Copyright (c) 2018 Oracle and/or its affiliates. All rights reserved.
3 | #
4 | # Licensed under the Apache License, Version 2.0 (the "License");
5 | # you may not use this file except in compliance with the License.
6 | # You may obtain a copy of the License at
7 | #
8 | # http://www.apache.org/licenses/LICENSE-2.0
9 | #
10 | # Unless required by applicable law or agreed to in writing, software
11 | # distributed under the License is distributed on an "AS IS" BASIS,
12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | # See the License for the specific language governing permissions and
14 | # limitations under the License.
15 | #
16 |
17 | # Example Logging Configuration File
18 | # For more information see $JAVA_HOME/jre/lib/logging.properties
19 |
20 | # Send messages to the console
21 | handlers=java.util.logging.ConsoleHandler
22 |
23 | # Global default logging level. Can be overriden by specific handlers and loggers
24 | .level=INFO
25 |
26 | # Helidon Web Server has a custom log formatter that extends SimpleFormatter.
27 | # It replaces "!thread!" with the current thread name
28 | java.util.logging.ConsoleHandler.level=INFO
29 | java.util.logging.ConsoleHandler.formatter=io.helidon.webserver.netty.WebServerLogFormatter
30 | java.util.logging.SimpleFormatter.format=%1$tY.%1$tm.%1$td %1$tH:%1$tM:%1$tS %4$s %3$s !thread!: %5$s%6$s%n
31 |
32 | #Component specific log levels
33 | #io.helidon.webserver.level=INFO
34 | #io.helidon.config.level=INFO
35 | #io.helidon.security.level=INFO
36 | #io.helidon.common.level=INFO
37 | #io.netty.level=INFO
38 |
--------------------------------------------------------------------------------
/src/test/java/evolution/ConfigReaderTest.java:
--------------------------------------------------------------------------------
1 | package evolution;
2 |
3 | import evolution.configuration.ConfigReader;
4 | import evolution.factory.daoparser.DaoParserTypeEnum;
5 | import evolution.factory.daoparser.DaoParserProvider;
6 | import org.junit.jupiter.api.Test;
7 |
8 | class ConfigReaderTest {
9 |
10 | @Test
11 | void should_get_correct_dao_parse_type_as_config_setting() {
12 | DaoParserProvider reader = new ConfigReader();
13 | DaoParserTypeEnum daoParserType = reader.getDaoParserType();
14 | assert(daoParserType).equals(DaoParserTypeEnum.MyBatisParser);
15 | }
16 | }
--------------------------------------------------------------------------------
/src/test/java/evolution/MainTest.java:
--------------------------------------------------------------------------------
1 | package evolution;
2 |
3 |
4 | import io.helidon.webserver.WebServer;
5 | import org.junit.jupiter.api.AfterAll;
6 | import org.junit.jupiter.api.Assertions;
7 | import org.junit.jupiter.api.BeforeAll;
8 | import org.junit.jupiter.api.Test;
9 |
10 | import javax.json.Json;
11 | import javax.json.JsonObject;
12 | import javax.json.JsonReader;
13 | import java.net.HttpURLConnection;
14 | import java.net.URL;
15 | import java.util.concurrent.TimeUnit;
16 |
17 | public class MainTest {
18 |
19 | private static WebServer webServer;
20 |
21 | @BeforeAll
22 | public static void startTheServer() throws Exception {
23 | webServer = Main.startServer();
24 | while (! webServer.isRunning()) {
25 | Thread.sleep(1 * 1000);
26 | }
27 | }
28 |
29 | @AfterAll
30 | public static void stopServer() throws Exception {
31 | if (webServer != null) {
32 | webServer.shutdown()
33 | .toCompletableFuture()
34 | .get(10, TimeUnit.SECONDS);
35 | }
36 | }
37 |
38 | @Test
39 | public void testHelloWorld() throws Exception {
40 | HttpURLConnection conn;
41 |
42 | conn = getURLConnection("GET", "/greet/Joe");
43 | Assertions.assertEquals(200, conn.getResponseCode(), "HTTP response2");
44 | JsonReader jsonReader = Json.createReader(conn.getInputStream());
45 | JsonObject jsonObject = jsonReader.readObject();
46 | Assertions.assertEquals("Hello Joe!", jsonObject.getString("message"),
47 | "hello Joe message");
48 |
49 | conn = getURLConnection("PUT", "/greet/greeting/Hola");
50 | Assertions.assertEquals(200, conn.getResponseCode(), "HTTP response3");
51 | conn = getURLConnection("GET", "/greet/Jose");
52 | Assertions.assertEquals(200, conn.getResponseCode(), "HTTP response4");
53 | jsonReader = Json.createReader(conn.getInputStream());
54 | jsonObject = jsonReader.readObject();
55 | Assertions.assertEquals("Hola Jose!", jsonObject.getString("message"),
56 | "hola Jose message");
57 | }
58 |
59 | private HttpURLConnection getURLConnection(String method, String path) throws Exception {
60 | URL url = new URL("http://localhost:" + webServer.port() + path);
61 | HttpURLConnection conn = (HttpURLConnection) url.openConnection();
62 | conn.setRequestMethod(method);
63 | conn.setRequestProperty("Accept", "application/json");
64 | return conn;
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/src/test/java/evolution/analysis/jv/calls/plugins/JavaCallVisitorTest.java:
--------------------------------------------------------------------------------
1 | package evolution.analysis.jv.calls.plugins;
2 |
3 | import org.junit.jupiter.api.Assertions;
4 | import org.junit.jupiter.api.Test;
5 |
6 | import java.util.List;
7 | import java.util.stream.Stream;
8 |
9 | public class JavaCallVisitorTest {
10 |
11 | private JavaDaoStringParser visitor = new JavaDaoStringParser();
12 | @Test
13 | public void testParseProcedureCalls() {
14 | String body = "Stringsql=\"{call PKG_LS_CLM_CALC.P_GET_ANXIN_PRO_AMOUNT(?,?,?)} \";";
15 | List res = visitor.parseProcedureCalls(body);
16 | Assertions.assertEquals(1,res.size());
17 | Assertions.assertEquals("PKG_LS_CLM_CALC.P_GET_ANXIN_PRO_AMOUNT",res.get(0));
18 |
19 | String body2 = "Stringsql=\" \"; " +
20 | "Stringsql=\"{call PKG_LS_CLM_CALC.P_GET_ANXIN_PRO_AMOUNT2(?,?,?)} \";";
21 | List res2 = visitor.parseProcedureCalls(body2);
22 | Assertions.assertEquals(1,res2.size());
23 | Assertions.assertEquals("PKG_LS_CLM_CALC.P_GET_ANXIN_PRO_AMOUNT2",res2.get(0));
24 |
25 | String body3 = "Stringsql=\"{call PKG_LS_CLM_CALC.P_GET_ANXIN_PRO_AMOUNT(?,?,?)} \";" +
26 | "Stringsql=\"{call PKG_LS_CLM_CALC.P_GET_ANXIN_PRO_AMOUNT2(?,?,?)} \";";
27 | List res3 = visitor.parseProcedureCalls(body3);
28 | Assertions.assertEquals(2,res3.size());
29 | Assertions.assertEquals("PKG_LS_CLM_CALC.P_GET_ANXIN_PRO_AMOUNT",res3.get(0));
30 | Assertions.assertEquals("PKG_LS_CLM_CALC.P_GET_ANXIN_PRO_AMOUNT2",res3.get(1));
31 | }
32 |
33 | @Test
34 | public void testParseTables() {
35 | String body = "newStringBuffer(\"select distinct tclp.item_id,\").append(\" tpl.liab_id,\").append(\" tprl.product_abbr,\").append(\" tprl.product_name,\").append(\" tliab.liab_name\").append(\" from t_Liab_Pay_Relative tpl,\").append(\" t_claim_product tclp,\").append(\" t_product_life tprl,\").append(\" t_liability tliab,\").append(\" t_contract_master tcm\").append(\" where tclp.policy_id = ? and tclp.product_id = tpl.product_id and\").append(\" tliab.liab_id = tpl.liab_id and\").append(\" tclp.product_id = tprl.product_id and tclp.case_id = ? and\").append(\" tcm.policy_id = tclp.policy_id \")";
36 | List res = visitor.parseTables(body);
37 | Stream.of(res).forEach(System.out::println);
38 | Assertions.assertEquals(10,res.size());
39 | Assertions.assertEquals("SELECT",res.get(0));
40 | }
41 |
42 |
43 | @Test
44 | public void cleanTableName() {
45 | Assertions.assertEquals("T_HEALTH_PRODUCT_SPECIAL", visitor.cleanTableName("T_HEALTH_PRODUCT_SPECIAL)\\N"));
46 | Assertions.assertEquals("T_HEALTH_PRODUCT_SPECIAL", visitor.cleanTableName("T_HEALTH_PRODUCT_SPECIAL)"));
47 | Assertions.assertEquals("T_HEALTH_PRODUCT_SPECIAL", visitor.cleanTableName("T_HEALTH_PRODUCT_SPECIAL"));
48 | Assertions.assertEquals("T_CONTRACT_MASTER_LIAB_HI", visitor.cleanTableName("T_CONTRACT_MASTER_LIAB_HI"));
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/src/test/java/evolution/factory/daoparser/FakeConfigReader.java:
--------------------------------------------------------------------------------
1 | package evolution.factory.daoparser;
2 |
3 | public class FakeConfigReader implements DaoParserProvider {
4 | private final DaoParserTypeEnum daoParserTypeEnum;
5 | private final String parsRootPath;
6 |
7 | public FakeConfigReader(DaoParserTypeEnum daoParserTypeEnum, String parsRootPath) {
8 | this.daoParserTypeEnum = daoParserTypeEnum;
9 | this.parsRootPath = parsRootPath;
10 | }
11 |
12 | @Override
13 | public DaoParserTypeEnum getDaoParserType() {
14 | return this.daoParserTypeEnum;
15 | }
16 |
17 | @Override
18 | public String getDaoParseRootPath() {
19 | return this.parsRootPath;
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/src/test/java/evolution/factory/daoparser/JavaDaoParserFactoryTest.java:
--------------------------------------------------------------------------------
1 | package evolution.factory.daoparser;
2 |
3 | import evolution.analysis.jv.calls.JavaDaoParser;
4 | import evolution.analysis.jv.calls.plugins.JavaDaoStringParser;
5 | import evolution.analysis.jv.calls.plugins.MyBatisParser;
6 | import org.junit.jupiter.api.Test;
7 |
8 | import static org.hamcrest.MatcherAssert.assertThat;
9 | import static org.hamcrest.Matchers.instanceOf;
10 |
11 | class JavaDaoParserFactoryTest {
12 |
13 | @Test
14 | void should_create_myBatis_parser_when_type_is_mybatis() {
15 | DaoParserProvider provider = new FakeConfigReader(DaoParserTypeEnum.MyBatisParser, "");
16 | JavaDaoParserFactory factory = new JavaDaoParserFactory(provider);
17 | JavaDaoParser daoParser = factory.createDaoParser();
18 |
19 | assertThat(daoParser, instanceOf(MyBatisParser.class));
20 | }
21 |
22 | @Test
23 | void should_create_java_string_dao_parser_when_type_is_stringParser() {
24 | DaoParserProvider provider = new FakeConfigReader(DaoParserTypeEnum.StringParser, "");
25 | JavaDaoParserFactory factory = new JavaDaoParserFactory(provider);
26 | JavaDaoParser daoParser = factory.createDaoParser();
27 |
28 | assertThat(daoParser, instanceOf(JavaDaoStringParser.class));
29 | }
30 |
31 | }
--------------------------------------------------------------------------------