diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index bc778a2..2f1d564 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -14,7 +14,7 @@ jobs: - name: Set up Go uses: actions/setup-go@v4 with: - go-version: '1.20' + go-version: '1.22.0' - name: Check out code uses: actions/checkout@v3 diff --git a/.gitignore b/.gitignore index e492922..32db93e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,4 @@ example-java-project/ -main sourcecode-parser/pathfinder .idea/ .gradle/ diff --git a/sourcecode-parser/antlr/Query.g4 b/sourcecode-parser/antlr/Query.g4 new file mode 100644 index 0000000..fc1cb31 --- /dev/null +++ b/sourcecode-parser/antlr/Query.g4 @@ -0,0 +1,25 @@ +grammar Query; + +query : 'FIND' select_list ('WHERE' expression)? ; +select_list : select_item (',' select_item)* ; +select_item : entity 'AS' alias ; +entity : IDENTIFIER ; +alias : IDENTIFIER ; +expression : orExpression ; +orExpression : andExpression ( '||' andExpression )* ; +andExpression : primary ( '&&' primary )* ; +primary : condition + | '(' expression ')' ; +condition : alias '.' method_chain comparator (value | method_chain | '(' value_list ')') ; +method_chain : method_or_variable ('.' method_or_variable)* ; +method_or_variable : method | variable ; +method : IDENTIFIER '(' ')' ; +variable : IDENTIFIER ; +comparator : '==' | '!=' | '<' | '>' | '<=' | '>=' | 'LIKE' | 'IN' ; +value : STRING | NUMBER | STRING_WITH_WILDCARD ; +value_list : value (',' value)* ; +STRING : '"' ( ~('"' | '\\') | '\\' . )* '"' ; +STRING_WITH_WILDCARD : '"' ( ~('"' | '\\') | '\\' . | '%' )* '"' ; +NUMBER : [0-9]+ ('.' [0-9]+)? ; +IDENTIFIER : [a-zA-Z_][a-zA-Z0-9_]* ; +WS : [ \t\r\n]+ -> skip ; diff --git a/sourcecode-parser/antlr/Query.interp b/sourcecode-parser/antlr/Query.interp new file mode 100644 index 0000000..0e8e493 --- /dev/null +++ b/sourcecode-parser/antlr/Query.interp @@ -0,0 +1,72 @@ +token literal names: +null +'FIND' +'WHERE' +',' +'AS' +'||' +'&&' +'(' +')' +'.' +'==' +'!=' +'<' +'>' +'<=' +'>=' +'LIKE' +'IN' +null +null +null +null +null + +token symbolic names: +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +STRING +STRING_WITH_WILDCARD +NUMBER +IDENTIFIER +WS + +rule names: +query +select_list +select_item +entity +alias +expression +orExpression +andExpression +primary +condition +method_chain +method_or_variable +method +variable +comparator +value +value_list + + +atn: +[4, 1, 22, 124, 2, 0, 7, 0, 2, 1, 7, 1, 2, 2, 7, 2, 2, 3, 7, 3, 2, 4, 7, 4, 2, 5, 7, 5, 2, 6, 7, 6, 2, 7, 7, 7, 2, 8, 7, 8, 2, 9, 7, 9, 2, 10, 7, 10, 2, 11, 7, 11, 2, 12, 7, 12, 2, 13, 7, 13, 2, 14, 7, 14, 2, 15, 7, 15, 2, 16, 7, 16, 1, 0, 1, 0, 1, 0, 1, 0, 3, 0, 39, 8, 0, 1, 1, 1, 1, 1, 1, 5, 1, 44, 8, 1, 10, 1, 12, 1, 47, 9, 1, 1, 2, 1, 2, 1, 2, 1, 2, 1, 3, 1, 3, 1, 4, 1, 4, 1, 5, 1, 5, 1, 6, 1, 6, 1, 6, 5, 6, 62, 8, 6, 10, 6, 12, 6, 65, 9, 6, 1, 7, 1, 7, 1, 7, 5, 7, 70, 8, 7, 10, 7, 12, 7, 73, 9, 7, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 3, 8, 80, 8, 8, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 3, 9, 92, 8, 9, 1, 10, 1, 10, 1, 10, 5, 10, 97, 8, 10, 10, 10, 12, 10, 100, 9, 10, 1, 11, 1, 11, 3, 11, 104, 8, 11, 1, 12, 1, 12, 1, 12, 1, 12, 1, 13, 1, 13, 1, 14, 1, 14, 1, 15, 1, 15, 1, 16, 1, 16, 1, 16, 5, 16, 119, 8, 16, 10, 16, 12, 16, 122, 9, 16, 1, 16, 0, 0, 17, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 0, 2, 1, 0, 10, 17, 1, 0, 18, 20, 116, 0, 34, 1, 0, 0, 0, 2, 40, 1, 0, 0, 0, 4, 48, 1, 0, 0, 0, 6, 52, 1, 0, 0, 0, 8, 54, 1, 0, 0, 0, 10, 56, 1, 0, 0, 0, 12, 58, 1, 0, 0, 0, 14, 66, 1, 0, 0, 0, 16, 79, 1, 0, 0, 0, 18, 81, 1, 0, 0, 0, 20, 93, 1, 0, 0, 0, 22, 103, 1, 0, 0, 0, 24, 105, 1, 0, 0, 0, 26, 109, 1, 0, 0, 0, 28, 111, 1, 0, 0, 0, 30, 113, 1, 0, 0, 0, 32, 115, 1, 0, 0, 0, 34, 35, 5, 1, 0, 0, 35, 38, 3, 2, 1, 0, 36, 37, 5, 2, 0, 0, 37, 39, 3, 10, 5, 0, 38, 36, 1, 0, 0, 0, 38, 39, 1, 0, 0, 0, 39, 1, 1, 0, 0, 0, 40, 45, 3, 4, 2, 0, 41, 42, 5, 3, 0, 0, 42, 44, 3, 4, 2, 0, 43, 41, 1, 0, 0, 0, 44, 47, 1, 0, 0, 0, 45, 43, 1, 0, 0, 0, 45, 46, 1, 0, 0, 0, 46, 3, 1, 0, 0, 0, 47, 45, 1, 0, 0, 0, 48, 49, 3, 6, 3, 0, 49, 50, 5, 4, 0, 0, 50, 51, 3, 8, 4, 0, 51, 5, 1, 0, 0, 0, 52, 53, 5, 21, 0, 0, 53, 7, 1, 0, 0, 0, 54, 55, 5, 21, 0, 0, 55, 9, 1, 0, 0, 0, 56, 57, 3, 12, 6, 0, 57, 11, 1, 0, 0, 0, 58, 63, 3, 14, 7, 0, 59, 60, 5, 5, 0, 0, 60, 62, 3, 14, 7, 0, 61, 59, 1, 0, 0, 0, 62, 65, 1, 0, 0, 0, 63, 61, 1, 0, 0, 0, 63, 64, 1, 0, 0, 0, 64, 13, 1, 0, 0, 0, 65, 63, 1, 0, 0, 0, 66, 71, 3, 16, 8, 0, 67, 68, 5, 6, 0, 0, 68, 70, 3, 16, 8, 0, 69, 67, 1, 0, 0, 0, 70, 73, 1, 0, 0, 0, 71, 69, 1, 0, 0, 0, 71, 72, 1, 0, 0, 0, 72, 15, 1, 0, 0, 0, 73, 71, 1, 0, 0, 0, 74, 80, 3, 18, 9, 0, 75, 76, 5, 7, 0, 0, 76, 77, 3, 10, 5, 0, 77, 78, 5, 8, 0, 0, 78, 80, 1, 0, 0, 0, 79, 74, 1, 0, 0, 0, 79, 75, 1, 0, 0, 0, 80, 17, 1, 0, 0, 0, 81, 82, 3, 8, 4, 0, 82, 83, 5, 9, 0, 0, 83, 84, 3, 20, 10, 0, 84, 91, 3, 28, 14, 0, 85, 92, 3, 30, 15, 0, 86, 92, 3, 20, 10, 0, 87, 88, 5, 7, 0, 0, 88, 89, 3, 32, 16, 0, 89, 90, 5, 8, 0, 0, 90, 92, 1, 0, 0, 0, 91, 85, 1, 0, 0, 0, 91, 86, 1, 0, 0, 0, 91, 87, 1, 0, 0, 0, 92, 19, 1, 0, 0, 0, 93, 98, 3, 22, 11, 0, 94, 95, 5, 9, 0, 0, 95, 97, 3, 22, 11, 0, 96, 94, 1, 0, 0, 0, 97, 100, 1, 0, 0, 0, 98, 96, 1, 0, 0, 0, 98, 99, 1, 0, 0, 0, 99, 21, 1, 0, 0, 0, 100, 98, 1, 0, 0, 0, 101, 104, 3, 24, 12, 0, 102, 104, 3, 26, 13, 0, 103, 101, 1, 0, 0, 0, 103, 102, 1, 0, 0, 0, 104, 23, 1, 0, 0, 0, 105, 106, 5, 21, 0, 0, 106, 107, 5, 7, 0, 0, 107, 108, 5, 8, 0, 0, 108, 25, 1, 0, 0, 0, 109, 110, 5, 21, 0, 0, 110, 27, 1, 0, 0, 0, 111, 112, 7, 0, 0, 0, 112, 29, 1, 0, 0, 0, 113, 114, 7, 1, 0, 0, 114, 31, 1, 0, 0, 0, 115, 120, 3, 30, 15, 0, 116, 117, 5, 3, 0, 0, 117, 119, 3, 30, 15, 0, 118, 116, 1, 0, 0, 0, 119, 122, 1, 0, 0, 0, 120, 118, 1, 0, 0, 0, 120, 121, 1, 0, 0, 0, 121, 33, 1, 0, 0, 0, 122, 120, 1, 0, 0, 0, 9, 38, 45, 63, 71, 79, 91, 98, 103, 120] \ No newline at end of file diff --git a/sourcecode-parser/antlr/Query.tokens b/sourcecode-parser/antlr/Query.tokens new file mode 100644 index 0000000..aa6805e --- /dev/null +++ b/sourcecode-parser/antlr/Query.tokens @@ -0,0 +1,39 @@ +T__0=1 +T__1=2 +T__2=3 +T__3=4 +T__4=5 +T__5=6 +T__6=7 +T__7=8 +T__8=9 +T__9=10 +T__10=11 +T__11=12 +T__12=13 +T__13=14 +T__14=15 +T__15=16 +T__16=17 +STRING=18 +STRING_WITH_WILDCARD=19 +NUMBER=20 +IDENTIFIER=21 +WS=22 +'FIND'=1 +'WHERE'=2 +','=3 +'AS'=4 +'||'=5 +'&&'=6 +'('=7 +')'=8 +'.'=9 +'=='=10 +'!='=11 +'<'=12 +'>'=13 +'<='=14 +'>='=15 +'LIKE'=16 +'IN'=17 diff --git a/sourcecode-parser/antlr/QueryLexer.interp b/sourcecode-parser/antlr/QueryLexer.interp new file mode 100644 index 0000000..5ea6f50 --- /dev/null +++ b/sourcecode-parser/antlr/QueryLexer.interp @@ -0,0 +1,83 @@ +token literal names: +null +'FIND' +'WHERE' +',' +'AS' +'||' +'&&' +'(' +')' +'.' +'==' +'!=' +'<' +'>' +'<=' +'>=' +'LIKE' +'IN' +null +null +null +null +null + +token symbolic names: +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +STRING +STRING_WITH_WILDCARD +NUMBER +IDENTIFIER +WS + +rule names: +T__0 +T__1 +T__2 +T__3 +T__4 +T__5 +T__6 +T__7 +T__8 +T__9 +T__10 +T__11 +T__12 +T__13 +T__14 +T__15 +T__16 +STRING +STRING_WITH_WILDCARD +NUMBER +IDENTIFIER +WS + +channel names: +DEFAULT_TOKEN_CHANNEL +HIDDEN + +mode names: +DEFAULT_MODE + +atn: +[4, 0, 22, 147, 6, -1, 2, 0, 7, 0, 2, 1, 7, 1, 2, 2, 7, 2, 2, 3, 7, 3, 2, 4, 7, 4, 2, 5, 7, 5, 2, 6, 7, 6, 2, 7, 7, 7, 2, 8, 7, 8, 2, 9, 7, 9, 2, 10, 7, 10, 2, 11, 7, 11, 2, 12, 7, 12, 2, 13, 7, 13, 2, 14, 7, 14, 2, 15, 7, 15, 2, 16, 7, 16, 2, 17, 7, 17, 2, 18, 7, 18, 2, 19, 7, 19, 2, 20, 7, 20, 2, 21, 7, 21, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 2, 1, 3, 1, 3, 1, 3, 1, 4, 1, 4, 1, 4, 1, 5, 1, 5, 1, 5, 1, 6, 1, 6, 1, 7, 1, 7, 1, 8, 1, 8, 1, 9, 1, 9, 1, 9, 1, 10, 1, 10, 1, 10, 1, 11, 1, 11, 1, 12, 1, 12, 1, 13, 1, 13, 1, 13, 1, 14, 1, 14, 1, 14, 1, 15, 1, 15, 1, 15, 1, 15, 1, 15, 1, 16, 1, 16, 1, 16, 1, 17, 1, 17, 1, 17, 1, 17, 5, 17, 102, 8, 17, 10, 17, 12, 17, 105, 9, 17, 1, 17, 1, 17, 1, 18, 1, 18, 1, 18, 1, 18, 1, 18, 5, 18, 114, 8, 18, 10, 18, 12, 18, 117, 9, 18, 1, 18, 1, 18, 1, 19, 4, 19, 122, 8, 19, 11, 19, 12, 19, 123, 1, 19, 1, 19, 4, 19, 128, 8, 19, 11, 19, 12, 19, 129, 3, 19, 132, 8, 19, 1, 20, 1, 20, 5, 20, 136, 8, 20, 10, 20, 12, 20, 139, 9, 20, 1, 21, 4, 21, 142, 8, 21, 11, 21, 12, 21, 143, 1, 21, 1, 21, 0, 0, 22, 1, 1, 3, 2, 5, 3, 7, 4, 9, 5, 11, 6, 13, 7, 15, 8, 17, 9, 19, 10, 21, 11, 23, 12, 25, 13, 27, 14, 29, 15, 31, 16, 33, 17, 35, 18, 37, 19, 39, 20, 41, 21, 43, 22, 1, 0, 5, 2, 0, 34, 34, 92, 92, 1, 0, 48, 57, 3, 0, 65, 90, 95, 95, 97, 122, 4, 0, 48, 57, 65, 90, 95, 95, 97, 122, 3, 0, 9, 10, 13, 13, 32, 32, 156, 0, 1, 1, 0, 0, 0, 0, 3, 1, 0, 0, 0, 0, 5, 1, 0, 0, 0, 0, 7, 1, 0, 0, 0, 0, 9, 1, 0, 0, 0, 0, 11, 1, 0, 0, 0, 0, 13, 1, 0, 0, 0, 0, 15, 1, 0, 0, 0, 0, 17, 1, 0, 0, 0, 0, 19, 1, 0, 0, 0, 0, 21, 1, 0, 0, 0, 0, 23, 1, 0, 0, 0, 0, 25, 1, 0, 0, 0, 0, 27, 1, 0, 0, 0, 0, 29, 1, 0, 0, 0, 0, 31, 1, 0, 0, 0, 0, 33, 1, 0, 0, 0, 0, 35, 1, 0, 0, 0, 0, 37, 1, 0, 0, 0, 0, 39, 1, 0, 0, 0, 0, 41, 1, 0, 0, 0, 0, 43, 1, 0, 0, 0, 1, 45, 1, 0, 0, 0, 3, 50, 1, 0, 0, 0, 5, 56, 1, 0, 0, 0, 7, 58, 1, 0, 0, 0, 9, 61, 1, 0, 0, 0, 11, 64, 1, 0, 0, 0, 13, 67, 1, 0, 0, 0, 15, 69, 1, 0, 0, 0, 17, 71, 1, 0, 0, 0, 19, 73, 1, 0, 0, 0, 21, 76, 1, 0, 0, 0, 23, 79, 1, 0, 0, 0, 25, 81, 1, 0, 0, 0, 27, 83, 1, 0, 0, 0, 29, 86, 1, 0, 0, 0, 31, 89, 1, 0, 0, 0, 33, 94, 1, 0, 0, 0, 35, 97, 1, 0, 0, 0, 37, 108, 1, 0, 0, 0, 39, 121, 1, 0, 0, 0, 41, 133, 1, 0, 0, 0, 43, 141, 1, 0, 0, 0, 45, 46, 5, 70, 0, 0, 46, 47, 5, 73, 0, 0, 47, 48, 5, 78, 0, 0, 48, 49, 5, 68, 0, 0, 49, 2, 1, 0, 0, 0, 50, 51, 5, 87, 0, 0, 51, 52, 5, 72, 0, 0, 52, 53, 5, 69, 0, 0, 53, 54, 5, 82, 0, 0, 54, 55, 5, 69, 0, 0, 55, 4, 1, 0, 0, 0, 56, 57, 5, 44, 0, 0, 57, 6, 1, 0, 0, 0, 58, 59, 5, 65, 0, 0, 59, 60, 5, 83, 0, 0, 60, 8, 1, 0, 0, 0, 61, 62, 5, 124, 0, 0, 62, 63, 5, 124, 0, 0, 63, 10, 1, 0, 0, 0, 64, 65, 5, 38, 0, 0, 65, 66, 5, 38, 0, 0, 66, 12, 1, 0, 0, 0, 67, 68, 5, 40, 0, 0, 68, 14, 1, 0, 0, 0, 69, 70, 5, 41, 0, 0, 70, 16, 1, 0, 0, 0, 71, 72, 5, 46, 0, 0, 72, 18, 1, 0, 0, 0, 73, 74, 5, 61, 0, 0, 74, 75, 5, 61, 0, 0, 75, 20, 1, 0, 0, 0, 76, 77, 5, 33, 0, 0, 77, 78, 5, 61, 0, 0, 78, 22, 1, 0, 0, 0, 79, 80, 5, 60, 0, 0, 80, 24, 1, 0, 0, 0, 81, 82, 5, 62, 0, 0, 82, 26, 1, 0, 0, 0, 83, 84, 5, 60, 0, 0, 84, 85, 5, 61, 0, 0, 85, 28, 1, 0, 0, 0, 86, 87, 5, 62, 0, 0, 87, 88, 5, 61, 0, 0, 88, 30, 1, 0, 0, 0, 89, 90, 5, 76, 0, 0, 90, 91, 5, 73, 0, 0, 91, 92, 5, 75, 0, 0, 92, 93, 5, 69, 0, 0, 93, 32, 1, 0, 0, 0, 94, 95, 5, 73, 0, 0, 95, 96, 5, 78, 0, 0, 96, 34, 1, 0, 0, 0, 97, 103, 5, 34, 0, 0, 98, 102, 8, 0, 0, 0, 99, 100, 5, 92, 0, 0, 100, 102, 9, 0, 0, 0, 101, 98, 1, 0, 0, 0, 101, 99, 1, 0, 0, 0, 102, 105, 1, 0, 0, 0, 103, 101, 1, 0, 0, 0, 103, 104, 1, 0, 0, 0, 104, 106, 1, 0, 0, 0, 105, 103, 1, 0, 0, 0, 106, 107, 5, 34, 0, 0, 107, 36, 1, 0, 0, 0, 108, 115, 5, 34, 0, 0, 109, 114, 8, 0, 0, 0, 110, 111, 5, 92, 0, 0, 111, 114, 9, 0, 0, 0, 112, 114, 5, 37, 0, 0, 113, 109, 1, 0, 0, 0, 113, 110, 1, 0, 0, 0, 113, 112, 1, 0, 0, 0, 114, 117, 1, 0, 0, 0, 115, 113, 1, 0, 0, 0, 115, 116, 1, 0, 0, 0, 116, 118, 1, 0, 0, 0, 117, 115, 1, 0, 0, 0, 118, 119, 5, 34, 0, 0, 119, 38, 1, 0, 0, 0, 120, 122, 7, 1, 0, 0, 121, 120, 1, 0, 0, 0, 122, 123, 1, 0, 0, 0, 123, 121, 1, 0, 0, 0, 123, 124, 1, 0, 0, 0, 124, 131, 1, 0, 0, 0, 125, 127, 5, 46, 0, 0, 126, 128, 7, 1, 0, 0, 127, 126, 1, 0, 0, 0, 128, 129, 1, 0, 0, 0, 129, 127, 1, 0, 0, 0, 129, 130, 1, 0, 0, 0, 130, 132, 1, 0, 0, 0, 131, 125, 1, 0, 0, 0, 131, 132, 1, 0, 0, 0, 132, 40, 1, 0, 0, 0, 133, 137, 7, 2, 0, 0, 134, 136, 7, 3, 0, 0, 135, 134, 1, 0, 0, 0, 136, 139, 1, 0, 0, 0, 137, 135, 1, 0, 0, 0, 137, 138, 1, 0, 0, 0, 138, 42, 1, 0, 0, 0, 139, 137, 1, 0, 0, 0, 140, 142, 7, 4, 0, 0, 141, 140, 1, 0, 0, 0, 142, 143, 1, 0, 0, 0, 143, 141, 1, 0, 0, 0, 143, 144, 1, 0, 0, 0, 144, 145, 1, 0, 0, 0, 145, 146, 6, 21, 0, 0, 146, 44, 1, 0, 0, 0, 10, 0, 101, 103, 113, 115, 123, 129, 131, 137, 143, 1, 6, 0, 0] \ No newline at end of file diff --git a/sourcecode-parser/antlr/QueryLexer.tokens b/sourcecode-parser/antlr/QueryLexer.tokens new file mode 100644 index 0000000..aa6805e --- /dev/null +++ b/sourcecode-parser/antlr/QueryLexer.tokens @@ -0,0 +1,39 @@ +T__0=1 +T__1=2 +T__2=3 +T__3=4 +T__4=5 +T__5=6 +T__6=7 +T__7=8 +T__8=9 +T__9=10 +T__10=11 +T__11=12 +T__12=13 +T__13=14 +T__14=15 +T__15=16 +T__16=17 +STRING=18 +STRING_WITH_WILDCARD=19 +NUMBER=20 +IDENTIFIER=21 +WS=22 +'FIND'=1 +'WHERE'=2 +','=3 +'AS'=4 +'||'=5 +'&&'=6 +'('=7 +')'=8 +'.'=9 +'=='=10 +'!='=11 +'<'=12 +'>'=13 +'<='=14 +'>='=15 +'LIKE'=16 +'IN'=17 diff --git a/sourcecode-parser/antlr/listener_impl.go b/sourcecode-parser/antlr/listener_impl.go new file mode 100644 index 0000000..e909ef9 --- /dev/null +++ b/sourcecode-parser/antlr/listener_impl.go @@ -0,0 +1,93 @@ +package parser + +import ( + "strings" + + "github.com/antlr4-go/antlr/v4" +) + +type Query struct { + SelectList []SelectList + Expression string +} + +type CustomQueryListener struct { + BaseQueryListener + expression strings.Builder + selectList []SelectList +} + +type SelectList struct { + Entity string + Alias string +} + +func NewCustomQueryListener() *CustomQueryListener { + return &CustomQueryListener{ + BaseQueryListener: BaseQueryListener{}, + } +} + +//nolint:all +func (l *CustomQueryListener) EnterSelect_list(ctx *Select_listContext) { + for i := 0; i < ctx.GetChildCount(); i++ { + child := ctx.GetChild(i).(antlr.ParseTree) + if child, ok := child.(ISelect_itemContext); ok { + l.selectList = append(l.selectList, SelectList{ + Entity: child.Entity().GetText(), + Alias: child.Alias().GetText(), + }) + } + } +} + +func (l *CustomQueryListener) EnterExpression(ctx *ExpressionContext) { + if l.expression.Len() > 0 { + l.expression.WriteString(" ") + } + l.expression.WriteString(ctx.GetText()) +} + +func (l *CustomQueryListener) ExitOrExpression(ctx *OrExpressionContext) { + if ctx.GetChildCount() > 1 { + var result strings.Builder + for i := 0; i < ctx.GetChildCount(); i++ { + child := ctx.GetChild(i).(antlr.ParseTree) //nolint:all + if child.GetText() == "||" { + result.WriteString(" || ") + } else { + result.WriteString(child.GetText()) + } + } + l.expression.Reset() + l.expression.WriteString(result.String()) + } +} + +func (l *CustomQueryListener) ExitAndExpression(ctx *AndExpressionContext) { + if ctx.GetChildCount() > 1 { + var result strings.Builder + for i := 0; i < ctx.GetChildCount(); i++ { + child := ctx.GetChild(i).(antlr.ParseTree) //nolint:all + if child.GetText() == "&&" { + result.WriteString(" && ") + } else { + result.WriteString(child.GetText()) + } + } + l.expression.Reset() + l.expression.WriteString(result.String()) + } +} + +func ParseQuery(inputQuery string) Query { + inputStream := antlr.NewInputStream(inputQuery) + lexer := NewQueryLexer(inputStream) + stream := antlr.NewCommonTokenStream(lexer, antlr.TokenDefaultChannel) + p := NewQueryParser(stream) + + listener := NewCustomQueryListener() + antlr.ParseTreeWalkerDefault.Walk(listener, p.Query()) + + return Query{SelectList: listener.selectList, Expression: listener.expression.String()} +} diff --git a/sourcecode-parser/antlr/query_base_listener.go b/sourcecode-parser/antlr/query_base_listener.go new file mode 100644 index 0000000..d44a8d9 --- /dev/null +++ b/sourcecode-parser/antlr/query_base_listener.go @@ -0,0 +1,124 @@ +// Code generated from Query.g4 by ANTLR 4.13.1. DO NOT EDIT. + +package parser // Query + +import "github.com/antlr4-go/antlr/v4" + +// BaseQueryListener is a complete listener for a parse tree produced by QueryParser. +type BaseQueryListener struct{} + +var _ QueryListener = &BaseQueryListener{} + +// VisitTerminal is called when a terminal node is visited. +func (s *BaseQueryListener) VisitTerminal(node antlr.TerminalNode) {} + +// VisitErrorNode is called when an error node is visited. +func (s *BaseQueryListener) VisitErrorNode(node antlr.ErrorNode) {} + +// EnterEveryRule is called when any rule is entered. +func (s *BaseQueryListener) EnterEveryRule(ctx antlr.ParserRuleContext) {} + +// ExitEveryRule is called when any rule is exited. +func (s *BaseQueryListener) ExitEveryRule(ctx antlr.ParserRuleContext) {} + +// EnterQuery is called when production query is entered. +func (s *BaseQueryListener) EnterQuery(ctx *QueryContext) {} + +// ExitQuery is called when production query is exited. +func (s *BaseQueryListener) ExitQuery(ctx *QueryContext) {} + +// EnterSelect_list is called when production select_list is entered. +func (s *BaseQueryListener) EnterSelect_list(ctx *Select_listContext) {} + +// ExitSelect_list is called when production select_list is exited. +func (s *BaseQueryListener) ExitSelect_list(ctx *Select_listContext) {} + +// EnterSelect_item is called when production select_item is entered. +func (s *BaseQueryListener) EnterSelect_item(ctx *Select_itemContext) {} + +// ExitSelect_item is called when production select_item is exited. +func (s *BaseQueryListener) ExitSelect_item(ctx *Select_itemContext) {} + +// EnterEntity is called when production entity is entered. +func (s *BaseQueryListener) EnterEntity(ctx *EntityContext) {} + +// ExitEntity is called when production entity is exited. +func (s *BaseQueryListener) ExitEntity(ctx *EntityContext) {} + +// EnterAlias is called when production alias is entered. +func (s *BaseQueryListener) EnterAlias(ctx *AliasContext) {} + +// ExitAlias is called when production alias is exited. +func (s *BaseQueryListener) ExitAlias(ctx *AliasContext) {} + +// EnterExpression is called when production expression is entered. +func (s *BaseQueryListener) EnterExpression(ctx *ExpressionContext) {} + +// ExitExpression is called when production expression is exited. +func (s *BaseQueryListener) ExitExpression(ctx *ExpressionContext) {} + +// EnterOrExpression is called when production orExpression is entered. +func (s *BaseQueryListener) EnterOrExpression(ctx *OrExpressionContext) {} + +// ExitOrExpression is called when production orExpression is exited. +func (s *BaseQueryListener) ExitOrExpression(ctx *OrExpressionContext) {} + +// EnterAndExpression is called when production andExpression is entered. +func (s *BaseQueryListener) EnterAndExpression(ctx *AndExpressionContext) {} + +// ExitAndExpression is called when production andExpression is exited. +func (s *BaseQueryListener) ExitAndExpression(ctx *AndExpressionContext) {} + +// EnterPrimary is called when production primary is entered. +func (s *BaseQueryListener) EnterPrimary(ctx *PrimaryContext) {} + +// ExitPrimary is called when production primary is exited. +func (s *BaseQueryListener) ExitPrimary(ctx *PrimaryContext) {} + +// EnterCondition is called when production condition is entered. +func (s *BaseQueryListener) EnterCondition(ctx *ConditionContext) {} + +// ExitCondition is called when production condition is exited. +func (s *BaseQueryListener) ExitCondition(ctx *ConditionContext) {} + +// EnterMethod_chain is called when production method_chain is entered. +func (s *BaseQueryListener) EnterMethod_chain(ctx *Method_chainContext) {} + +// ExitMethod_chain is called when production method_chain is exited. +func (s *BaseQueryListener) ExitMethod_chain(ctx *Method_chainContext) {} + +// EnterMethod_or_variable is called when production method_or_variable is entered. +func (s *BaseQueryListener) EnterMethod_or_variable(ctx *Method_or_variableContext) {} + +// ExitMethod_or_variable is called when production method_or_variable is exited. +func (s *BaseQueryListener) ExitMethod_or_variable(ctx *Method_or_variableContext) {} + +// EnterMethod is called when production method is entered. +func (s *BaseQueryListener) EnterMethod(ctx *MethodContext) {} + +// ExitMethod is called when production method is exited. +func (s *BaseQueryListener) ExitMethod(ctx *MethodContext) {} + +// EnterVariable is called when production variable is entered. +func (s *BaseQueryListener) EnterVariable(ctx *VariableContext) {} + +// ExitVariable is called when production variable is exited. +func (s *BaseQueryListener) ExitVariable(ctx *VariableContext) {} + +// EnterComparator is called when production comparator is entered. +func (s *BaseQueryListener) EnterComparator(ctx *ComparatorContext) {} + +// ExitComparator is called when production comparator is exited. +func (s *BaseQueryListener) ExitComparator(ctx *ComparatorContext) {} + +// EnterValue is called when production value is entered. +func (s *BaseQueryListener) EnterValue(ctx *ValueContext) {} + +// ExitValue is called when production value is exited. +func (s *BaseQueryListener) ExitValue(ctx *ValueContext) {} + +// EnterValue_list is called when production value_list is entered. +func (s *BaseQueryListener) EnterValue_list(ctx *Value_listContext) {} + +// ExitValue_list is called when production value_list is exited. +func (s *BaseQueryListener) ExitValue_list(ctx *Value_listContext) {} diff --git a/sourcecode-parser/antlr/query_lexer.go b/sourcecode-parser/antlr/query_lexer.go new file mode 100644 index 0000000..fb03e7e --- /dev/null +++ b/sourcecode-parser/antlr/query_lexer.go @@ -0,0 +1,187 @@ +// Code generated from Query.g4 by ANTLR 4.13.1. DO NOT EDIT. + +package parser + +import ( + "fmt" + "github.com/antlr4-go/antlr/v4" + "sync" + "unicode" +) + +// Suppress unused import error +var _ = fmt.Printf +var _ = sync.Once{} +var _ = unicode.IsLetter + +type QueryLexer struct { + *antlr.BaseLexer + channelNames []string + modeNames []string + // TODO: EOF string +} + +var QueryLexerLexerStaticData struct { + once sync.Once + serializedATN []int32 + ChannelNames []string + ModeNames []string + LiteralNames []string + SymbolicNames []string + RuleNames []string + PredictionContextCache *antlr.PredictionContextCache + atn *antlr.ATN + decisionToDFA []*antlr.DFA +} + +func querylexerLexerInit() { + staticData := &QueryLexerLexerStaticData + staticData.ChannelNames = []string{ + "DEFAULT_TOKEN_CHANNEL", "HIDDEN", + } + staticData.ModeNames = []string{ + "DEFAULT_MODE", + } + staticData.LiteralNames = []string{ + "", "'FIND'", "'WHERE'", "','", "'AS'", "'||'", "'&&'", "'('", "')'", + "'.'", "'=='", "'!='", "'<'", "'>'", "'<='", "'>='", "'LIKE'", "'IN'", + } + staticData.SymbolicNames = []string{ + "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", + "", "STRING", "STRING_WITH_WILDCARD", "NUMBER", "IDENTIFIER", "WS", + } + staticData.RuleNames = []string{ + "T__0", "T__1", "T__2", "T__3", "T__4", "T__5", "T__6", "T__7", "T__8", + "T__9", "T__10", "T__11", "T__12", "T__13", "T__14", "T__15", "T__16", + "STRING", "STRING_WITH_WILDCARD", "NUMBER", "IDENTIFIER", "WS", + } + staticData.PredictionContextCache = antlr.NewPredictionContextCache() + staticData.serializedATN = []int32{ + 4, 0, 22, 147, 6, -1, 2, 0, 7, 0, 2, 1, 7, 1, 2, 2, 7, 2, 2, 3, 7, 3, 2, + 4, 7, 4, 2, 5, 7, 5, 2, 6, 7, 6, 2, 7, 7, 7, 2, 8, 7, 8, 2, 9, 7, 9, 2, + 10, 7, 10, 2, 11, 7, 11, 2, 12, 7, 12, 2, 13, 7, 13, 2, 14, 7, 14, 2, 15, + 7, 15, 2, 16, 7, 16, 2, 17, 7, 17, 2, 18, 7, 18, 2, 19, 7, 19, 2, 20, 7, + 20, 2, 21, 7, 21, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 2, 1, 2, 1, 3, 1, 3, 1, 3, 1, 4, 1, 4, 1, 4, 1, 5, 1, 5, + 1, 5, 1, 6, 1, 6, 1, 7, 1, 7, 1, 8, 1, 8, 1, 9, 1, 9, 1, 9, 1, 10, 1, 10, + 1, 10, 1, 11, 1, 11, 1, 12, 1, 12, 1, 13, 1, 13, 1, 13, 1, 14, 1, 14, 1, + 14, 1, 15, 1, 15, 1, 15, 1, 15, 1, 15, 1, 16, 1, 16, 1, 16, 1, 17, 1, 17, + 1, 17, 1, 17, 5, 17, 102, 8, 17, 10, 17, 12, 17, 105, 9, 17, 1, 17, 1, + 17, 1, 18, 1, 18, 1, 18, 1, 18, 1, 18, 5, 18, 114, 8, 18, 10, 18, 12, 18, + 117, 9, 18, 1, 18, 1, 18, 1, 19, 4, 19, 122, 8, 19, 11, 19, 12, 19, 123, + 1, 19, 1, 19, 4, 19, 128, 8, 19, 11, 19, 12, 19, 129, 3, 19, 132, 8, 19, + 1, 20, 1, 20, 5, 20, 136, 8, 20, 10, 20, 12, 20, 139, 9, 20, 1, 21, 4, + 21, 142, 8, 21, 11, 21, 12, 21, 143, 1, 21, 1, 21, 0, 0, 22, 1, 1, 3, 2, + 5, 3, 7, 4, 9, 5, 11, 6, 13, 7, 15, 8, 17, 9, 19, 10, 21, 11, 23, 12, 25, + 13, 27, 14, 29, 15, 31, 16, 33, 17, 35, 18, 37, 19, 39, 20, 41, 21, 43, + 22, 1, 0, 5, 2, 0, 34, 34, 92, 92, 1, 0, 48, 57, 3, 0, 65, 90, 95, 95, + 97, 122, 4, 0, 48, 57, 65, 90, 95, 95, 97, 122, 3, 0, 9, 10, 13, 13, 32, + 32, 156, 0, 1, 1, 0, 0, 0, 0, 3, 1, 0, 0, 0, 0, 5, 1, 0, 0, 0, 0, 7, 1, + 0, 0, 0, 0, 9, 1, 0, 0, 0, 0, 11, 1, 0, 0, 0, 0, 13, 1, 0, 0, 0, 0, 15, + 1, 0, 0, 0, 0, 17, 1, 0, 0, 0, 0, 19, 1, 0, 0, 0, 0, 21, 1, 0, 0, 0, 0, + 23, 1, 0, 0, 0, 0, 25, 1, 0, 0, 0, 0, 27, 1, 0, 0, 0, 0, 29, 1, 0, 0, 0, + 0, 31, 1, 0, 0, 0, 0, 33, 1, 0, 0, 0, 0, 35, 1, 0, 0, 0, 0, 37, 1, 0, 0, + 0, 0, 39, 1, 0, 0, 0, 0, 41, 1, 0, 0, 0, 0, 43, 1, 0, 0, 0, 1, 45, 1, 0, + 0, 0, 3, 50, 1, 0, 0, 0, 5, 56, 1, 0, 0, 0, 7, 58, 1, 0, 0, 0, 9, 61, 1, + 0, 0, 0, 11, 64, 1, 0, 0, 0, 13, 67, 1, 0, 0, 0, 15, 69, 1, 0, 0, 0, 17, + 71, 1, 0, 0, 0, 19, 73, 1, 0, 0, 0, 21, 76, 1, 0, 0, 0, 23, 79, 1, 0, 0, + 0, 25, 81, 1, 0, 0, 0, 27, 83, 1, 0, 0, 0, 29, 86, 1, 0, 0, 0, 31, 89, + 1, 0, 0, 0, 33, 94, 1, 0, 0, 0, 35, 97, 1, 0, 0, 0, 37, 108, 1, 0, 0, 0, + 39, 121, 1, 0, 0, 0, 41, 133, 1, 0, 0, 0, 43, 141, 1, 0, 0, 0, 45, 46, + 5, 70, 0, 0, 46, 47, 5, 73, 0, 0, 47, 48, 5, 78, 0, 0, 48, 49, 5, 68, 0, + 0, 49, 2, 1, 0, 0, 0, 50, 51, 5, 87, 0, 0, 51, 52, 5, 72, 0, 0, 52, 53, + 5, 69, 0, 0, 53, 54, 5, 82, 0, 0, 54, 55, 5, 69, 0, 0, 55, 4, 1, 0, 0, + 0, 56, 57, 5, 44, 0, 0, 57, 6, 1, 0, 0, 0, 58, 59, 5, 65, 0, 0, 59, 60, + 5, 83, 0, 0, 60, 8, 1, 0, 0, 0, 61, 62, 5, 124, 0, 0, 62, 63, 5, 124, 0, + 0, 63, 10, 1, 0, 0, 0, 64, 65, 5, 38, 0, 0, 65, 66, 5, 38, 0, 0, 66, 12, + 1, 0, 0, 0, 67, 68, 5, 40, 0, 0, 68, 14, 1, 0, 0, 0, 69, 70, 5, 41, 0, + 0, 70, 16, 1, 0, 0, 0, 71, 72, 5, 46, 0, 0, 72, 18, 1, 0, 0, 0, 73, 74, + 5, 61, 0, 0, 74, 75, 5, 61, 0, 0, 75, 20, 1, 0, 0, 0, 76, 77, 5, 33, 0, + 0, 77, 78, 5, 61, 0, 0, 78, 22, 1, 0, 0, 0, 79, 80, 5, 60, 0, 0, 80, 24, + 1, 0, 0, 0, 81, 82, 5, 62, 0, 0, 82, 26, 1, 0, 0, 0, 83, 84, 5, 60, 0, + 0, 84, 85, 5, 61, 0, 0, 85, 28, 1, 0, 0, 0, 86, 87, 5, 62, 0, 0, 87, 88, + 5, 61, 0, 0, 88, 30, 1, 0, 0, 0, 89, 90, 5, 76, 0, 0, 90, 91, 5, 73, 0, + 0, 91, 92, 5, 75, 0, 0, 92, 93, 5, 69, 0, 0, 93, 32, 1, 0, 0, 0, 94, 95, + 5, 73, 0, 0, 95, 96, 5, 78, 0, 0, 96, 34, 1, 0, 0, 0, 97, 103, 5, 34, 0, + 0, 98, 102, 8, 0, 0, 0, 99, 100, 5, 92, 0, 0, 100, 102, 9, 0, 0, 0, 101, + 98, 1, 0, 0, 0, 101, 99, 1, 0, 0, 0, 102, 105, 1, 0, 0, 0, 103, 101, 1, + 0, 0, 0, 103, 104, 1, 0, 0, 0, 104, 106, 1, 0, 0, 0, 105, 103, 1, 0, 0, + 0, 106, 107, 5, 34, 0, 0, 107, 36, 1, 0, 0, 0, 108, 115, 5, 34, 0, 0, 109, + 114, 8, 0, 0, 0, 110, 111, 5, 92, 0, 0, 111, 114, 9, 0, 0, 0, 112, 114, + 5, 37, 0, 0, 113, 109, 1, 0, 0, 0, 113, 110, 1, 0, 0, 0, 113, 112, 1, 0, + 0, 0, 114, 117, 1, 0, 0, 0, 115, 113, 1, 0, 0, 0, 115, 116, 1, 0, 0, 0, + 116, 118, 1, 0, 0, 0, 117, 115, 1, 0, 0, 0, 118, 119, 5, 34, 0, 0, 119, + 38, 1, 0, 0, 0, 120, 122, 7, 1, 0, 0, 121, 120, 1, 0, 0, 0, 122, 123, 1, + 0, 0, 0, 123, 121, 1, 0, 0, 0, 123, 124, 1, 0, 0, 0, 124, 131, 1, 0, 0, + 0, 125, 127, 5, 46, 0, 0, 126, 128, 7, 1, 0, 0, 127, 126, 1, 0, 0, 0, 128, + 129, 1, 0, 0, 0, 129, 127, 1, 0, 0, 0, 129, 130, 1, 0, 0, 0, 130, 132, + 1, 0, 0, 0, 131, 125, 1, 0, 0, 0, 131, 132, 1, 0, 0, 0, 132, 40, 1, 0, + 0, 0, 133, 137, 7, 2, 0, 0, 134, 136, 7, 3, 0, 0, 135, 134, 1, 0, 0, 0, + 136, 139, 1, 0, 0, 0, 137, 135, 1, 0, 0, 0, 137, 138, 1, 0, 0, 0, 138, + 42, 1, 0, 0, 0, 139, 137, 1, 0, 0, 0, 140, 142, 7, 4, 0, 0, 141, 140, 1, + 0, 0, 0, 142, 143, 1, 0, 0, 0, 143, 141, 1, 0, 0, 0, 143, 144, 1, 0, 0, + 0, 144, 145, 1, 0, 0, 0, 145, 146, 6, 21, 0, 0, 146, 44, 1, 0, 0, 0, 10, + 0, 101, 103, 113, 115, 123, 129, 131, 137, 143, 1, 6, 0, 0, + } + deserializer := antlr.NewATNDeserializer(nil) + staticData.atn = deserializer.Deserialize(staticData.serializedATN) + atn := staticData.atn + staticData.decisionToDFA = make([]*antlr.DFA, len(atn.DecisionToState)) + decisionToDFA := staticData.decisionToDFA + for index, state := range atn.DecisionToState { + decisionToDFA[index] = antlr.NewDFA(state, index) + } +} + +// QueryLexerInit initializes any static state used to implement QueryLexer. By default the +// static state used to implement the lexer is lazily initialized during the first call to +// NewQueryLexer(). You can call this function if you wish to initialize the static state ahead +// of time. +func QueryLexerInit() { + staticData := &QueryLexerLexerStaticData + staticData.once.Do(querylexerLexerInit) +} + +// NewQueryLexer produces a new lexer instance for the optional input antlr.CharStream. +func NewQueryLexer(input antlr.CharStream) *QueryLexer { + QueryLexerInit() + l := new(QueryLexer) + l.BaseLexer = antlr.NewBaseLexer(input) + staticData := &QueryLexerLexerStaticData + l.Interpreter = antlr.NewLexerATNSimulator(l, staticData.atn, staticData.decisionToDFA, staticData.PredictionContextCache) + l.channelNames = staticData.ChannelNames + l.modeNames = staticData.ModeNames + l.RuleNames = staticData.RuleNames + l.LiteralNames = staticData.LiteralNames + l.SymbolicNames = staticData.SymbolicNames + l.GrammarFileName = "Query.g4" + // TODO: l.EOF = antlr.TokenEOF + + return l +} + +// QueryLexer tokens. +const ( + QueryLexerT__0 = 1 + QueryLexerT__1 = 2 + QueryLexerT__2 = 3 + QueryLexerT__3 = 4 + QueryLexerT__4 = 5 + QueryLexerT__5 = 6 + QueryLexerT__6 = 7 + QueryLexerT__7 = 8 + QueryLexerT__8 = 9 + QueryLexerT__9 = 10 + QueryLexerT__10 = 11 + QueryLexerT__11 = 12 + QueryLexerT__12 = 13 + QueryLexerT__13 = 14 + QueryLexerT__14 = 15 + QueryLexerT__15 = 16 + QueryLexerT__16 = 17 + QueryLexerSTRING = 18 + QueryLexerSTRING_WITH_WILDCARD = 19 + QueryLexerNUMBER = 20 + QueryLexerIDENTIFIER = 21 + QueryLexerWS = 22 +) diff --git a/sourcecode-parser/antlr/query_listener.go b/sourcecode-parser/antlr/query_listener.go new file mode 100644 index 0000000..29301cf --- /dev/null +++ b/sourcecode-parser/antlr/query_listener.go @@ -0,0 +1,112 @@ +// Code generated from Query.g4 by ANTLR 4.13.1. DO NOT EDIT. + +package parser // Query + +import "github.com/antlr4-go/antlr/v4" + +// QueryListener is a complete listener for a parse tree produced by QueryParser. +type QueryListener interface { + antlr.ParseTreeListener + + // EnterQuery is called when entering the query production. + EnterQuery(c *QueryContext) + + // EnterSelect_list is called when entering the select_list production. + EnterSelect_list(c *Select_listContext) + + // EnterSelect_item is called when entering the select_item production. + EnterSelect_item(c *Select_itemContext) + + // EnterEntity is called when entering the entity production. + EnterEntity(c *EntityContext) + + // EnterAlias is called when entering the alias production. + EnterAlias(c *AliasContext) + + // EnterExpression is called when entering the expression production. + EnterExpression(c *ExpressionContext) + + // EnterOrExpression is called when entering the orExpression production. + EnterOrExpression(c *OrExpressionContext) + + // EnterAndExpression is called when entering the andExpression production. + EnterAndExpression(c *AndExpressionContext) + + // EnterPrimary is called when entering the primary production. + EnterPrimary(c *PrimaryContext) + + // EnterCondition is called when entering the condition production. + EnterCondition(c *ConditionContext) + + // EnterMethod_chain is called when entering the method_chain production. + EnterMethod_chain(c *Method_chainContext) + + // EnterMethod_or_variable is called when entering the method_or_variable production. + EnterMethod_or_variable(c *Method_or_variableContext) + + // EnterMethod is called when entering the method production. + EnterMethod(c *MethodContext) + + // EnterVariable is called when entering the variable production. + EnterVariable(c *VariableContext) + + // EnterComparator is called when entering the comparator production. + EnterComparator(c *ComparatorContext) + + // EnterValue is called when entering the value production. + EnterValue(c *ValueContext) + + // EnterValue_list is called when entering the value_list production. + EnterValue_list(c *Value_listContext) + + // ExitQuery is called when exiting the query production. + ExitQuery(c *QueryContext) + + // ExitSelect_list is called when exiting the select_list production. + ExitSelect_list(c *Select_listContext) + + // ExitSelect_item is called when exiting the select_item production. + ExitSelect_item(c *Select_itemContext) + + // ExitEntity is called when exiting the entity production. + ExitEntity(c *EntityContext) + + // ExitAlias is called when exiting the alias production. + ExitAlias(c *AliasContext) + + // ExitExpression is called when exiting the expression production. + ExitExpression(c *ExpressionContext) + + // ExitOrExpression is called when exiting the orExpression production. + ExitOrExpression(c *OrExpressionContext) + + // ExitAndExpression is called when exiting the andExpression production. + ExitAndExpression(c *AndExpressionContext) + + // ExitPrimary is called when exiting the primary production. + ExitPrimary(c *PrimaryContext) + + // ExitCondition is called when exiting the condition production. + ExitCondition(c *ConditionContext) + + // ExitMethod_chain is called when exiting the method_chain production. + ExitMethod_chain(c *Method_chainContext) + + // ExitMethod_or_variable is called when exiting the method_or_variable production. + ExitMethod_or_variable(c *Method_or_variableContext) + + // ExitMethod is called when exiting the method production. + ExitMethod(c *MethodContext) + + // ExitVariable is called when exiting the variable production. + ExitVariable(c *VariableContext) + + // ExitComparator is called when exiting the comparator production. + ExitComparator(c *ComparatorContext) + + // ExitValue is called when exiting the value production. + ExitValue(c *ValueContext) + + // ExitValue_list is called when exiting the value_list production. + ExitValue_list(c *Value_listContext) +} diff --git a/sourcecode-parser/antlr/query_parser.go b/sourcecode-parser/antlr/query_parser.go new file mode 100644 index 0000000..99cdbce --- /dev/null +++ b/sourcecode-parser/antlr/query_parser.go @@ -0,0 +1,2528 @@ +// Code generated from Query.g4 by ANTLR 4.13.1. DO NOT EDIT. + +package parser // Query + +import ( + "fmt" + "strconv" + "sync" + + "github.com/antlr4-go/antlr/v4" +) + +// Suppress unused import errors +var _ = fmt.Printf +var _ = strconv.Itoa +var _ = sync.Once{} + +type QueryParser struct { + *antlr.BaseParser +} + +var QueryParserStaticData struct { + once sync.Once + serializedATN []int32 + LiteralNames []string + SymbolicNames []string + RuleNames []string + PredictionContextCache *antlr.PredictionContextCache + atn *antlr.ATN + decisionToDFA []*antlr.DFA +} + +func queryParserInit() { + staticData := &QueryParserStaticData + staticData.LiteralNames = []string{ + "", "'FIND'", "'WHERE'", "','", "'AS'", "'||'", "'&&'", "'('", "')'", + "'.'", "'=='", "'!='", "'<'", "'>'", "'<='", "'>='", "'LIKE'", "'IN'", + } + staticData.SymbolicNames = []string{ + "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", + "", "STRING", "STRING_WITH_WILDCARD", "NUMBER", "IDENTIFIER", "WS", + } + staticData.RuleNames = []string{ + "query", "select_list", "select_item", "entity", "alias", "expression", + "orExpression", "andExpression", "primary", "condition", "method_chain", + "method_or_variable", "method", "variable", "comparator", "value", "value_list", + } + staticData.PredictionContextCache = antlr.NewPredictionContextCache() + staticData.serializedATN = []int32{ + 4, 1, 22, 124, 2, 0, 7, 0, 2, 1, 7, 1, 2, 2, 7, 2, 2, 3, 7, 3, 2, 4, 7, + 4, 2, 5, 7, 5, 2, 6, 7, 6, 2, 7, 7, 7, 2, 8, 7, 8, 2, 9, 7, 9, 2, 10, 7, + 10, 2, 11, 7, 11, 2, 12, 7, 12, 2, 13, 7, 13, 2, 14, 7, 14, 2, 15, 7, 15, + 2, 16, 7, 16, 1, 0, 1, 0, 1, 0, 1, 0, 3, 0, 39, 8, 0, 1, 1, 1, 1, 1, 1, + 5, 1, 44, 8, 1, 10, 1, 12, 1, 47, 9, 1, 1, 2, 1, 2, 1, 2, 1, 2, 1, 3, 1, + 3, 1, 4, 1, 4, 1, 5, 1, 5, 1, 6, 1, 6, 1, 6, 5, 6, 62, 8, 6, 10, 6, 12, + 6, 65, 9, 6, 1, 7, 1, 7, 1, 7, 5, 7, 70, 8, 7, 10, 7, 12, 7, 73, 9, 7, + 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 3, 8, 80, 8, 8, 1, 9, 1, 9, 1, 9, 1, 9, 1, + 9, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 3, 9, 92, 8, 9, 1, 10, 1, 10, 1, 10, 5, + 10, 97, 8, 10, 10, 10, 12, 10, 100, 9, 10, 1, 11, 1, 11, 3, 11, 104, 8, + 11, 1, 12, 1, 12, 1, 12, 1, 12, 1, 13, 1, 13, 1, 14, 1, 14, 1, 15, 1, 15, + 1, 16, 1, 16, 1, 16, 5, 16, 119, 8, 16, 10, 16, 12, 16, 122, 9, 16, 1, + 16, 0, 0, 17, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, + 32, 0, 2, 1, 0, 10, 17, 1, 0, 18, 20, 116, 0, 34, 1, 0, 0, 0, 2, 40, 1, + 0, 0, 0, 4, 48, 1, 0, 0, 0, 6, 52, 1, 0, 0, 0, 8, 54, 1, 0, 0, 0, 10, 56, + 1, 0, 0, 0, 12, 58, 1, 0, 0, 0, 14, 66, 1, 0, 0, 0, 16, 79, 1, 0, 0, 0, + 18, 81, 1, 0, 0, 0, 20, 93, 1, 0, 0, 0, 22, 103, 1, 0, 0, 0, 24, 105, 1, + 0, 0, 0, 26, 109, 1, 0, 0, 0, 28, 111, 1, 0, 0, 0, 30, 113, 1, 0, 0, 0, + 32, 115, 1, 0, 0, 0, 34, 35, 5, 1, 0, 0, 35, 38, 3, 2, 1, 0, 36, 37, 5, + 2, 0, 0, 37, 39, 3, 10, 5, 0, 38, 36, 1, 0, 0, 0, 38, 39, 1, 0, 0, 0, 39, + 1, 1, 0, 0, 0, 40, 45, 3, 4, 2, 0, 41, 42, 5, 3, 0, 0, 42, 44, 3, 4, 2, + 0, 43, 41, 1, 0, 0, 0, 44, 47, 1, 0, 0, 0, 45, 43, 1, 0, 0, 0, 45, 46, + 1, 0, 0, 0, 46, 3, 1, 0, 0, 0, 47, 45, 1, 0, 0, 0, 48, 49, 3, 6, 3, 0, + 49, 50, 5, 4, 0, 0, 50, 51, 3, 8, 4, 0, 51, 5, 1, 0, 0, 0, 52, 53, 5, 21, + 0, 0, 53, 7, 1, 0, 0, 0, 54, 55, 5, 21, 0, 0, 55, 9, 1, 0, 0, 0, 56, 57, + 3, 12, 6, 0, 57, 11, 1, 0, 0, 0, 58, 63, 3, 14, 7, 0, 59, 60, 5, 5, 0, + 0, 60, 62, 3, 14, 7, 0, 61, 59, 1, 0, 0, 0, 62, 65, 1, 0, 0, 0, 63, 61, + 1, 0, 0, 0, 63, 64, 1, 0, 0, 0, 64, 13, 1, 0, 0, 0, 65, 63, 1, 0, 0, 0, + 66, 71, 3, 16, 8, 0, 67, 68, 5, 6, 0, 0, 68, 70, 3, 16, 8, 0, 69, 67, 1, + 0, 0, 0, 70, 73, 1, 0, 0, 0, 71, 69, 1, 0, 0, 0, 71, 72, 1, 0, 0, 0, 72, + 15, 1, 0, 0, 0, 73, 71, 1, 0, 0, 0, 74, 80, 3, 18, 9, 0, 75, 76, 5, 7, + 0, 0, 76, 77, 3, 10, 5, 0, 77, 78, 5, 8, 0, 0, 78, 80, 1, 0, 0, 0, 79, + 74, 1, 0, 0, 0, 79, 75, 1, 0, 0, 0, 80, 17, 1, 0, 0, 0, 81, 82, 3, 8, 4, + 0, 82, 83, 5, 9, 0, 0, 83, 84, 3, 20, 10, 0, 84, 91, 3, 28, 14, 0, 85, + 92, 3, 30, 15, 0, 86, 92, 3, 20, 10, 0, 87, 88, 5, 7, 0, 0, 88, 89, 3, + 32, 16, 0, 89, 90, 5, 8, 0, 0, 90, 92, 1, 0, 0, 0, 91, 85, 1, 0, 0, 0, + 91, 86, 1, 0, 0, 0, 91, 87, 1, 0, 0, 0, 92, 19, 1, 0, 0, 0, 93, 98, 3, + 22, 11, 0, 94, 95, 5, 9, 0, 0, 95, 97, 3, 22, 11, 0, 96, 94, 1, 0, 0, 0, + 97, 100, 1, 0, 0, 0, 98, 96, 1, 0, 0, 0, 98, 99, 1, 0, 0, 0, 99, 21, 1, + 0, 0, 0, 100, 98, 1, 0, 0, 0, 101, 104, 3, 24, 12, 0, 102, 104, 3, 26, + 13, 0, 103, 101, 1, 0, 0, 0, 103, 102, 1, 0, 0, 0, 104, 23, 1, 0, 0, 0, + 105, 106, 5, 21, 0, 0, 106, 107, 5, 7, 0, 0, 107, 108, 5, 8, 0, 0, 108, + 25, 1, 0, 0, 0, 109, 110, 5, 21, 0, 0, 110, 27, 1, 0, 0, 0, 111, 112, 7, + 0, 0, 0, 112, 29, 1, 0, 0, 0, 113, 114, 7, 1, 0, 0, 114, 31, 1, 0, 0, 0, + 115, 120, 3, 30, 15, 0, 116, 117, 5, 3, 0, 0, 117, 119, 3, 30, 15, 0, 118, + 116, 1, 0, 0, 0, 119, 122, 1, 0, 0, 0, 120, 118, 1, 0, 0, 0, 120, 121, + 1, 0, 0, 0, 121, 33, 1, 0, 0, 0, 122, 120, 1, 0, 0, 0, 9, 38, 45, 63, 71, + 79, 91, 98, 103, 120, + } + deserializer := antlr.NewATNDeserializer(nil) + staticData.atn = deserializer.Deserialize(staticData.serializedATN) + atn := staticData.atn + staticData.decisionToDFA = make([]*antlr.DFA, len(atn.DecisionToState)) + decisionToDFA := staticData.decisionToDFA + for index, state := range atn.DecisionToState { + decisionToDFA[index] = antlr.NewDFA(state, index) + } +} + +// QueryParserInit initializes any static state used to implement QueryParser. By default the +// static state used to implement the parser is lazily initialized during the first call to +// NewQueryParser(). You can call this function if you wish to initialize the static state ahead +// of time. +func QueryParserInit() { + staticData := &QueryParserStaticData + staticData.once.Do(queryParserInit) +} + +// NewQueryParser produces a new parser instance for the optional input antlr.TokenStream. +func NewQueryParser(input antlr.TokenStream) *QueryParser { + QueryParserInit() + this := new(QueryParser) + this.BaseParser = antlr.NewBaseParser(input) + staticData := &QueryParserStaticData + this.Interpreter = antlr.NewParserATNSimulator(this, staticData.atn, staticData.decisionToDFA, staticData.PredictionContextCache) + this.RuleNames = staticData.RuleNames + this.LiteralNames = staticData.LiteralNames + this.SymbolicNames = staticData.SymbolicNames + this.GrammarFileName = "Query.g4" + + return this +} + +// QueryParser tokens. +const ( + QueryParserEOF = antlr.TokenEOF + QueryParserT__0 = 1 + QueryParserT__1 = 2 + QueryParserT__2 = 3 + QueryParserT__3 = 4 + QueryParserT__4 = 5 + QueryParserT__5 = 6 + QueryParserT__6 = 7 + QueryParserT__7 = 8 + QueryParserT__8 = 9 + QueryParserT__9 = 10 + QueryParserT__10 = 11 + QueryParserT__11 = 12 + QueryParserT__12 = 13 + QueryParserT__13 = 14 + QueryParserT__14 = 15 + QueryParserT__15 = 16 + QueryParserT__16 = 17 + QueryParserSTRING = 18 + QueryParserSTRING_WITH_WILDCARD = 19 + QueryParserNUMBER = 20 + QueryParserIDENTIFIER = 21 + QueryParserWS = 22 +) + +// QueryParser rules. +const ( + QueryParserRULE_query = 0 + QueryParserRULE_select_list = 1 + QueryParserRULE_select_item = 2 + QueryParserRULE_entity = 3 + QueryParserRULE_alias = 4 + QueryParserRULE_expression = 5 + QueryParserRULE_orExpression = 6 + QueryParserRULE_andExpression = 7 + QueryParserRULE_primary = 8 + QueryParserRULE_condition = 9 + QueryParserRULE_method_chain = 10 + QueryParserRULE_method_or_variable = 11 + QueryParserRULE_method = 12 + QueryParserRULE_variable = 13 + QueryParserRULE_comparator = 14 + QueryParserRULE_value = 15 + QueryParserRULE_value_list = 16 +) + +// IQueryContext is an interface to support dynamic dispatch. +type IQueryContext interface { + antlr.ParserRuleContext + + // GetParser returns the parser. + GetParser() antlr.Parser + + // Getter signatures + Select_list() ISelect_listContext + Expression() IExpressionContext + + // IsQueryContext differentiates from other interfaces. + IsQueryContext() +} + +type QueryContext struct { + antlr.BaseParserRuleContext + parser antlr.Parser +} + +func NewEmptyQueryContext() *QueryContext { + var p = new(QueryContext) + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1) + p.RuleIndex = QueryParserRULE_query + return p +} + +func InitEmptyQueryContext(p *QueryContext) { + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1) + p.RuleIndex = QueryParserRULE_query +} + +func (*QueryContext) IsQueryContext() {} + +func NewQueryContext(parser antlr.Parser, parent antlr.ParserRuleContext, invokingState int) *QueryContext { + var p = new(QueryContext) + + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, parent, invokingState) + + p.parser = parser + p.RuleIndex = QueryParserRULE_query + + return p +} + +func (s *QueryContext) GetParser() antlr.Parser { return s.parser } + +func (s *QueryContext) Select_list() ISelect_listContext { + var t antlr.RuleContext + for _, ctx := range s.GetChildren() { + if _, ok := ctx.(ISelect_listContext); ok { + t = ctx.(antlr.RuleContext) + break + } + } + + if t == nil { + return nil + } + + return t.(ISelect_listContext) +} + +func (s *QueryContext) Expression() IExpressionContext { + var t antlr.RuleContext + for _, ctx := range s.GetChildren() { + if _, ok := ctx.(IExpressionContext); ok { + t = ctx.(antlr.RuleContext) + break + } + } + + if t == nil { + return nil + } + + return t.(IExpressionContext) +} + +func (s *QueryContext) GetRuleContext() antlr.RuleContext { + return s +} + +func (s *QueryContext) ToStringTree(ruleNames []string, recog antlr.Recognizer) string { + return antlr.TreesStringTree(s, ruleNames, recog) +} + +func (s *QueryContext) EnterRule(listener antlr.ParseTreeListener) { + if listenerT, ok := listener.(QueryListener); ok { + listenerT.EnterQuery(s) + } +} + +func (s *QueryContext) ExitRule(listener antlr.ParseTreeListener) { + if listenerT, ok := listener.(QueryListener); ok { + listenerT.ExitQuery(s) + } +} + +func (p *QueryParser) Query() (localctx IQueryContext) { + localctx = NewQueryContext(p, p.GetParserRuleContext(), p.GetState()) + p.EnterRule(localctx, 0, QueryParserRULE_query) + var _la int + + p.EnterOuterAlt(localctx, 1) + { + p.SetState(34) + p.Match(QueryParserT__0) + if p.HasError() { + // Recognition error - abort rule + goto errorExit + } + } + { + p.SetState(35) + p.Select_list() + } + p.SetState(38) + p.GetErrorHandler().Sync(p) + if p.HasError() { + goto errorExit + } + _la = p.GetTokenStream().LA(1) + + if _la == QueryParserT__1 { + { + p.SetState(36) + p.Match(QueryParserT__1) + if p.HasError() { + // Recognition error - abort rule + goto errorExit + } + } + { + p.SetState(37) + p.Expression() + } + + } + +errorExit: + if p.HasError() { + v := p.GetError() + localctx.SetException(v) + p.GetErrorHandler().ReportError(p, v) + p.GetErrorHandler().Recover(p, v) + p.SetError(nil) + } + p.ExitRule() + return localctx + goto errorExit // Trick to prevent compiler error if the label is not used +} + +// ISelect_listContext is an interface to support dynamic dispatch. +type ISelect_listContext interface { + antlr.ParserRuleContext + + // GetParser returns the parser. + GetParser() antlr.Parser + + // Getter signatures + AllSelect_item() []ISelect_itemContext + Select_item(i int) ISelect_itemContext + + // IsSelect_listContext differentiates from other interfaces. + IsSelect_listContext() +} + +type Select_listContext struct { + antlr.BaseParserRuleContext + parser antlr.Parser +} + +func NewEmptySelect_listContext() *Select_listContext { + var p = new(Select_listContext) + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1) + p.RuleIndex = QueryParserRULE_select_list + return p +} + +func InitEmptySelect_listContext(p *Select_listContext) { + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1) + p.RuleIndex = QueryParserRULE_select_list +} + +func (*Select_listContext) IsSelect_listContext() {} + +func NewSelect_listContext(parser antlr.Parser, parent antlr.ParserRuleContext, invokingState int) *Select_listContext { + var p = new(Select_listContext) + + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, parent, invokingState) + + p.parser = parser + p.RuleIndex = QueryParserRULE_select_list + + return p +} + +func (s *Select_listContext) GetParser() antlr.Parser { return s.parser } + +func (s *Select_listContext) AllSelect_item() []ISelect_itemContext { + children := s.GetChildren() + len := 0 + for _, ctx := range children { + if _, ok := ctx.(ISelect_itemContext); ok { + len++ + } + } + + tst := make([]ISelect_itemContext, len) + i := 0 + for _, ctx := range children { + if t, ok := ctx.(ISelect_itemContext); ok { + tst[i] = t.(ISelect_itemContext) + i++ + } + } + + return tst +} + +func (s *Select_listContext) Select_item(i int) ISelect_itemContext { + var t antlr.RuleContext + j := 0 + for _, ctx := range s.GetChildren() { + if _, ok := ctx.(ISelect_itemContext); ok { + if j == i { + t = ctx.(antlr.RuleContext) + break + } + j++ + } + } + + if t == nil { + return nil + } + + return t.(ISelect_itemContext) +} + +func (s *Select_listContext) GetRuleContext() antlr.RuleContext { + return s +} + +func (s *Select_listContext) ToStringTree(ruleNames []string, recog antlr.Recognizer) string { + return antlr.TreesStringTree(s, ruleNames, recog) +} + +func (s *Select_listContext) EnterRule(listener antlr.ParseTreeListener) { + if listenerT, ok := listener.(QueryListener); ok { + listenerT.EnterSelect_list(s) + } +} + +func (s *Select_listContext) ExitRule(listener antlr.ParseTreeListener) { + if listenerT, ok := listener.(QueryListener); ok { + listenerT.ExitSelect_list(s) + } +} + +func (p *QueryParser) Select_list() (localctx ISelect_listContext) { + localctx = NewSelect_listContext(p, p.GetParserRuleContext(), p.GetState()) + p.EnterRule(localctx, 2, QueryParserRULE_select_list) + var _la int + + p.EnterOuterAlt(localctx, 1) + { + p.SetState(40) + p.Select_item() + } + p.SetState(45) + p.GetErrorHandler().Sync(p) + if p.HasError() { + goto errorExit + } + _la = p.GetTokenStream().LA(1) + + for _la == QueryParserT__2 { + { + p.SetState(41) + p.Match(QueryParserT__2) + if p.HasError() { + // Recognition error - abort rule + goto errorExit + } + } + { + p.SetState(42) + p.Select_item() + } + + p.SetState(47) + p.GetErrorHandler().Sync(p) + if p.HasError() { + goto errorExit + } + _la = p.GetTokenStream().LA(1) + } + +errorExit: + if p.HasError() { + v := p.GetError() + localctx.SetException(v) + p.GetErrorHandler().ReportError(p, v) + p.GetErrorHandler().Recover(p, v) + p.SetError(nil) + } + p.ExitRule() + return localctx + goto errorExit // Trick to prevent compiler error if the label is not used +} + +// ISelect_itemContext is an interface to support dynamic dispatch. +type ISelect_itemContext interface { + antlr.ParserRuleContext + + // GetParser returns the parser. + GetParser() antlr.Parser + + // Getter signatures + Entity() IEntityContext + Alias() IAliasContext + + // IsSelect_itemContext differentiates from other interfaces. + IsSelect_itemContext() +} + +type Select_itemContext struct { + antlr.BaseParserRuleContext + parser antlr.Parser +} + +func NewEmptySelect_itemContext() *Select_itemContext { + var p = new(Select_itemContext) + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1) + p.RuleIndex = QueryParserRULE_select_item + return p +} + +func InitEmptySelect_itemContext(p *Select_itemContext) { + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1) + p.RuleIndex = QueryParserRULE_select_item +} + +func (*Select_itemContext) IsSelect_itemContext() {} + +func NewSelect_itemContext(parser antlr.Parser, parent antlr.ParserRuleContext, invokingState int) *Select_itemContext { + var p = new(Select_itemContext) + + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, parent, invokingState) + + p.parser = parser + p.RuleIndex = QueryParserRULE_select_item + + return p +} + +func (s *Select_itemContext) GetParser() antlr.Parser { return s.parser } + +func (s *Select_itemContext) Entity() IEntityContext { + var t antlr.RuleContext + for _, ctx := range s.GetChildren() { + if _, ok := ctx.(IEntityContext); ok { + t = ctx.(antlr.RuleContext) + break + } + } + + if t == nil { + return nil + } + + return t.(IEntityContext) +} + +func (s *Select_itemContext) Alias() IAliasContext { + var t antlr.RuleContext + for _, ctx := range s.GetChildren() { + if _, ok := ctx.(IAliasContext); ok { + t = ctx.(antlr.RuleContext) + break + } + } + + if t == nil { + return nil + } + + return t.(IAliasContext) +} + +func (s *Select_itemContext) GetRuleContext() antlr.RuleContext { + return s +} + +func (s *Select_itemContext) ToStringTree(ruleNames []string, recog antlr.Recognizer) string { + return antlr.TreesStringTree(s, ruleNames, recog) +} + +func (s *Select_itemContext) EnterRule(listener antlr.ParseTreeListener) { + if listenerT, ok := listener.(QueryListener); ok { + listenerT.EnterSelect_item(s) + } +} + +func (s *Select_itemContext) ExitRule(listener antlr.ParseTreeListener) { + if listenerT, ok := listener.(QueryListener); ok { + listenerT.ExitSelect_item(s) + } +} + +func (p *QueryParser) Select_item() (localctx ISelect_itemContext) { + localctx = NewSelect_itemContext(p, p.GetParserRuleContext(), p.GetState()) + p.EnterRule(localctx, 4, QueryParserRULE_select_item) + p.EnterOuterAlt(localctx, 1) + { + p.SetState(48) + p.Entity() + } + { + p.SetState(49) + p.Match(QueryParserT__3) + if p.HasError() { + // Recognition error - abort rule + goto errorExit + } + } + { + p.SetState(50) + p.Alias() + } + +errorExit: + if p.HasError() { + v := p.GetError() + localctx.SetException(v) + p.GetErrorHandler().ReportError(p, v) + p.GetErrorHandler().Recover(p, v) + p.SetError(nil) + } + p.ExitRule() + return localctx + goto errorExit // Trick to prevent compiler error if the label is not used +} + +// IEntityContext is an interface to support dynamic dispatch. +type IEntityContext interface { + antlr.ParserRuleContext + + // GetParser returns the parser. + GetParser() antlr.Parser + + // Getter signatures + IDENTIFIER() antlr.TerminalNode + + // IsEntityContext differentiates from other interfaces. + IsEntityContext() +} + +type EntityContext struct { + antlr.BaseParserRuleContext + parser antlr.Parser +} + +func NewEmptyEntityContext() *EntityContext { + var p = new(EntityContext) + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1) + p.RuleIndex = QueryParserRULE_entity + return p +} + +func InitEmptyEntityContext(p *EntityContext) { + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1) + p.RuleIndex = QueryParserRULE_entity +} + +func (*EntityContext) IsEntityContext() {} + +func NewEntityContext(parser antlr.Parser, parent antlr.ParserRuleContext, invokingState int) *EntityContext { + var p = new(EntityContext) + + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, parent, invokingState) + + p.parser = parser + p.RuleIndex = QueryParserRULE_entity + + return p +} + +func (s *EntityContext) GetParser() antlr.Parser { return s.parser } + +func (s *EntityContext) IDENTIFIER() antlr.TerminalNode { + return s.GetToken(QueryParserIDENTIFIER, 0) +} + +func (s *EntityContext) GetRuleContext() antlr.RuleContext { + return s +} + +func (s *EntityContext) ToStringTree(ruleNames []string, recog antlr.Recognizer) string { + return antlr.TreesStringTree(s, ruleNames, recog) +} + +func (s *EntityContext) EnterRule(listener antlr.ParseTreeListener) { + if listenerT, ok := listener.(QueryListener); ok { + listenerT.EnterEntity(s) + } +} + +func (s *EntityContext) ExitRule(listener antlr.ParseTreeListener) { + if listenerT, ok := listener.(QueryListener); ok { + listenerT.ExitEntity(s) + } +} + +func (p *QueryParser) Entity() (localctx IEntityContext) { + localctx = NewEntityContext(p, p.GetParserRuleContext(), p.GetState()) + p.EnterRule(localctx, 6, QueryParserRULE_entity) + p.EnterOuterAlt(localctx, 1) + { + p.SetState(52) + p.Match(QueryParserIDENTIFIER) + if p.HasError() { + // Recognition error - abort rule + goto errorExit + } + } + +errorExit: + if p.HasError() { + v := p.GetError() + localctx.SetException(v) + p.GetErrorHandler().ReportError(p, v) + p.GetErrorHandler().Recover(p, v) + p.SetError(nil) + } + p.ExitRule() + return localctx + goto errorExit // Trick to prevent compiler error if the label is not used +} + +// IAliasContext is an interface to support dynamic dispatch. +type IAliasContext interface { + antlr.ParserRuleContext + + // GetParser returns the parser. + GetParser() antlr.Parser + + // Getter signatures + IDENTIFIER() antlr.TerminalNode + + // IsAliasContext differentiates from other interfaces. + IsAliasContext() +} + +type AliasContext struct { + antlr.BaseParserRuleContext + parser antlr.Parser +} + +func NewEmptyAliasContext() *AliasContext { + var p = new(AliasContext) + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1) + p.RuleIndex = QueryParserRULE_alias + return p +} + +func InitEmptyAliasContext(p *AliasContext) { + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1) + p.RuleIndex = QueryParserRULE_alias +} + +func (*AliasContext) IsAliasContext() {} + +func NewAliasContext(parser antlr.Parser, parent antlr.ParserRuleContext, invokingState int) *AliasContext { + var p = new(AliasContext) + + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, parent, invokingState) + + p.parser = parser + p.RuleIndex = QueryParserRULE_alias + + return p +} + +func (s *AliasContext) GetParser() antlr.Parser { return s.parser } + +func (s *AliasContext) IDENTIFIER() antlr.TerminalNode { + return s.GetToken(QueryParserIDENTIFIER, 0) +} + +func (s *AliasContext) GetRuleContext() antlr.RuleContext { + return s +} + +func (s *AliasContext) ToStringTree(ruleNames []string, recog antlr.Recognizer) string { + return antlr.TreesStringTree(s, ruleNames, recog) +} + +func (s *AliasContext) EnterRule(listener antlr.ParseTreeListener) { + if listenerT, ok := listener.(QueryListener); ok { + listenerT.EnterAlias(s) + } +} + +func (s *AliasContext) ExitRule(listener antlr.ParseTreeListener) { + if listenerT, ok := listener.(QueryListener); ok { + listenerT.ExitAlias(s) + } +} + +func (p *QueryParser) Alias() (localctx IAliasContext) { + localctx = NewAliasContext(p, p.GetParserRuleContext(), p.GetState()) + p.EnterRule(localctx, 8, QueryParserRULE_alias) + p.EnterOuterAlt(localctx, 1) + { + p.SetState(54) + p.Match(QueryParserIDENTIFIER) + if p.HasError() { + // Recognition error - abort rule + goto errorExit + } + } + +errorExit: + if p.HasError() { + v := p.GetError() + localctx.SetException(v) + p.GetErrorHandler().ReportError(p, v) + p.GetErrorHandler().Recover(p, v) + p.SetError(nil) + } + p.ExitRule() + return localctx + goto errorExit // Trick to prevent compiler error if the label is not used +} + +// IExpressionContext is an interface to support dynamic dispatch. +type IExpressionContext interface { + antlr.ParserRuleContext + + // GetParser returns the parser. + GetParser() antlr.Parser + + // Getter signatures + OrExpression() IOrExpressionContext + + // IsExpressionContext differentiates from other interfaces. + IsExpressionContext() +} + +type ExpressionContext struct { + antlr.BaseParserRuleContext + parser antlr.Parser +} + +func NewEmptyExpressionContext() *ExpressionContext { + var p = new(ExpressionContext) + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1) + p.RuleIndex = QueryParserRULE_expression + return p +} + +func InitEmptyExpressionContext(p *ExpressionContext) { + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1) + p.RuleIndex = QueryParserRULE_expression +} + +func (*ExpressionContext) IsExpressionContext() {} + +func NewExpressionContext(parser antlr.Parser, parent antlr.ParserRuleContext, invokingState int) *ExpressionContext { + var p = new(ExpressionContext) + + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, parent, invokingState) + + p.parser = parser + p.RuleIndex = QueryParserRULE_expression + + return p +} + +func (s *ExpressionContext) GetParser() antlr.Parser { return s.parser } + +func (s *ExpressionContext) OrExpression() IOrExpressionContext { + var t antlr.RuleContext + for _, ctx := range s.GetChildren() { + if _, ok := ctx.(IOrExpressionContext); ok { + t = ctx.(antlr.RuleContext) + break + } + } + + if t == nil { + return nil + } + + return t.(IOrExpressionContext) +} + +func (s *ExpressionContext) GetRuleContext() antlr.RuleContext { + return s +} + +func (s *ExpressionContext) ToStringTree(ruleNames []string, recog antlr.Recognizer) string { + return antlr.TreesStringTree(s, ruleNames, recog) +} + +func (s *ExpressionContext) EnterRule(listener antlr.ParseTreeListener) { + if listenerT, ok := listener.(QueryListener); ok { + listenerT.EnterExpression(s) + } +} + +func (s *ExpressionContext) ExitRule(listener antlr.ParseTreeListener) { + if listenerT, ok := listener.(QueryListener); ok { + listenerT.ExitExpression(s) + } +} + +func (p *QueryParser) Expression() (localctx IExpressionContext) { + localctx = NewExpressionContext(p, p.GetParserRuleContext(), p.GetState()) + p.EnterRule(localctx, 10, QueryParserRULE_expression) + p.EnterOuterAlt(localctx, 1) + { + p.SetState(56) + p.OrExpression() + } + +errorExit: + if p.HasError() { + v := p.GetError() + localctx.SetException(v) + p.GetErrorHandler().ReportError(p, v) + p.GetErrorHandler().Recover(p, v) + p.SetError(nil) + } + p.ExitRule() + return localctx + goto errorExit // Trick to prevent compiler error if the label is not used +} + +// IOrExpressionContext is an interface to support dynamic dispatch. +type IOrExpressionContext interface { + antlr.ParserRuleContext + + // GetParser returns the parser. + GetParser() antlr.Parser + + // Getter signatures + AllAndExpression() []IAndExpressionContext + AndExpression(i int) IAndExpressionContext + + // IsOrExpressionContext differentiates from other interfaces. + IsOrExpressionContext() +} + +type OrExpressionContext struct { + antlr.BaseParserRuleContext + parser antlr.Parser +} + +func NewEmptyOrExpressionContext() *OrExpressionContext { + var p = new(OrExpressionContext) + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1) + p.RuleIndex = QueryParserRULE_orExpression + return p +} + +func InitEmptyOrExpressionContext(p *OrExpressionContext) { + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1) + p.RuleIndex = QueryParserRULE_orExpression +} + +func (*OrExpressionContext) IsOrExpressionContext() {} + +func NewOrExpressionContext(parser antlr.Parser, parent antlr.ParserRuleContext, invokingState int) *OrExpressionContext { + var p = new(OrExpressionContext) + + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, parent, invokingState) + + p.parser = parser + p.RuleIndex = QueryParserRULE_orExpression + + return p +} + +func (s *OrExpressionContext) GetParser() antlr.Parser { return s.parser } + +func (s *OrExpressionContext) AllAndExpression() []IAndExpressionContext { + children := s.GetChildren() + len := 0 + for _, ctx := range children { + if _, ok := ctx.(IAndExpressionContext); ok { + len++ + } + } + + tst := make([]IAndExpressionContext, len) + i := 0 + for _, ctx := range children { + if t, ok := ctx.(IAndExpressionContext); ok { + tst[i] = t.(IAndExpressionContext) + i++ + } + } + + return tst +} + +func (s *OrExpressionContext) AndExpression(i int) IAndExpressionContext { + var t antlr.RuleContext + j := 0 + for _, ctx := range s.GetChildren() { + if _, ok := ctx.(IAndExpressionContext); ok { + if j == i { + t = ctx.(antlr.RuleContext) + break + } + j++ + } + } + + if t == nil { + return nil + } + + return t.(IAndExpressionContext) +} + +func (s *OrExpressionContext) GetRuleContext() antlr.RuleContext { + return s +} + +func (s *OrExpressionContext) ToStringTree(ruleNames []string, recog antlr.Recognizer) string { + return antlr.TreesStringTree(s, ruleNames, recog) +} + +func (s *OrExpressionContext) EnterRule(listener antlr.ParseTreeListener) { + if listenerT, ok := listener.(QueryListener); ok { + listenerT.EnterOrExpression(s) + } +} + +func (s *OrExpressionContext) ExitRule(listener antlr.ParseTreeListener) { + if listenerT, ok := listener.(QueryListener); ok { + listenerT.ExitOrExpression(s) + } +} + +func (p *QueryParser) OrExpression() (localctx IOrExpressionContext) { + localctx = NewOrExpressionContext(p, p.GetParserRuleContext(), p.GetState()) + p.EnterRule(localctx, 12, QueryParserRULE_orExpression) + var _la int + + p.EnterOuterAlt(localctx, 1) + { + p.SetState(58) + p.AndExpression() + } + p.SetState(63) + p.GetErrorHandler().Sync(p) + if p.HasError() { + goto errorExit + } + _la = p.GetTokenStream().LA(1) + + for _la == QueryParserT__4 { + { + p.SetState(59) + p.Match(QueryParserT__4) + if p.HasError() { + // Recognition error - abort rule + goto errorExit + } + } + { + p.SetState(60) + p.AndExpression() + } + + p.SetState(65) + p.GetErrorHandler().Sync(p) + if p.HasError() { + goto errorExit + } + _la = p.GetTokenStream().LA(1) + } + +errorExit: + if p.HasError() { + v := p.GetError() + localctx.SetException(v) + p.GetErrorHandler().ReportError(p, v) + p.GetErrorHandler().Recover(p, v) + p.SetError(nil) + } + p.ExitRule() + return localctx + goto errorExit // Trick to prevent compiler error if the label is not used +} + +// IAndExpressionContext is an interface to support dynamic dispatch. +type IAndExpressionContext interface { + antlr.ParserRuleContext + + // GetParser returns the parser. + GetParser() antlr.Parser + + // Getter signatures + AllPrimary() []IPrimaryContext + Primary(i int) IPrimaryContext + + // IsAndExpressionContext differentiates from other interfaces. + IsAndExpressionContext() +} + +type AndExpressionContext struct { + antlr.BaseParserRuleContext + parser antlr.Parser +} + +func NewEmptyAndExpressionContext() *AndExpressionContext { + var p = new(AndExpressionContext) + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1) + p.RuleIndex = QueryParserRULE_andExpression + return p +} + +func InitEmptyAndExpressionContext(p *AndExpressionContext) { + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1) + p.RuleIndex = QueryParserRULE_andExpression +} + +func (*AndExpressionContext) IsAndExpressionContext() {} + +func NewAndExpressionContext(parser antlr.Parser, parent antlr.ParserRuleContext, invokingState int) *AndExpressionContext { + var p = new(AndExpressionContext) + + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, parent, invokingState) + + p.parser = parser + p.RuleIndex = QueryParserRULE_andExpression + + return p +} + +func (s *AndExpressionContext) GetParser() antlr.Parser { return s.parser } + +func (s *AndExpressionContext) AllPrimary() []IPrimaryContext { + children := s.GetChildren() + len := 0 + for _, ctx := range children { + if _, ok := ctx.(IPrimaryContext); ok { + len++ + } + } + + tst := make([]IPrimaryContext, len) + i := 0 + for _, ctx := range children { + if t, ok := ctx.(IPrimaryContext); ok { + tst[i] = t.(IPrimaryContext) + i++ + } + } + + return tst +} + +func (s *AndExpressionContext) Primary(i int) IPrimaryContext { + var t antlr.RuleContext + j := 0 + for _, ctx := range s.GetChildren() { + if _, ok := ctx.(IPrimaryContext); ok { + if j == i { + t = ctx.(antlr.RuleContext) + break + } + j++ + } + } + + if t == nil { + return nil + } + + return t.(IPrimaryContext) +} + +func (s *AndExpressionContext) GetRuleContext() antlr.RuleContext { + return s +} + +func (s *AndExpressionContext) ToStringTree(ruleNames []string, recog antlr.Recognizer) string { + return antlr.TreesStringTree(s, ruleNames, recog) +} + +func (s *AndExpressionContext) EnterRule(listener antlr.ParseTreeListener) { + if listenerT, ok := listener.(QueryListener); ok { + listenerT.EnterAndExpression(s) + } +} + +func (s *AndExpressionContext) ExitRule(listener antlr.ParseTreeListener) { + if listenerT, ok := listener.(QueryListener); ok { + listenerT.ExitAndExpression(s) + } +} + +func (p *QueryParser) AndExpression() (localctx IAndExpressionContext) { + localctx = NewAndExpressionContext(p, p.GetParserRuleContext(), p.GetState()) + p.EnterRule(localctx, 14, QueryParserRULE_andExpression) + var _la int + + p.EnterOuterAlt(localctx, 1) + { + p.SetState(66) + p.Primary() + } + p.SetState(71) + p.GetErrorHandler().Sync(p) + if p.HasError() { + goto errorExit + } + _la = p.GetTokenStream().LA(1) + + for _la == QueryParserT__5 { + { + p.SetState(67) + p.Match(QueryParserT__5) + if p.HasError() { + // Recognition error - abort rule + goto errorExit + } + } + { + p.SetState(68) + p.Primary() + } + + p.SetState(73) + p.GetErrorHandler().Sync(p) + if p.HasError() { + goto errorExit + } + _la = p.GetTokenStream().LA(1) + } + +errorExit: + if p.HasError() { + v := p.GetError() + localctx.SetException(v) + p.GetErrorHandler().ReportError(p, v) + p.GetErrorHandler().Recover(p, v) + p.SetError(nil) + } + p.ExitRule() + return localctx + goto errorExit // Trick to prevent compiler error if the label is not used +} + +// IPrimaryContext is an interface to support dynamic dispatch. +type IPrimaryContext interface { + antlr.ParserRuleContext + + // GetParser returns the parser. + GetParser() antlr.Parser + + // Getter signatures + Condition() IConditionContext + Expression() IExpressionContext + + // IsPrimaryContext differentiates from other interfaces. + IsPrimaryContext() +} + +type PrimaryContext struct { + antlr.BaseParserRuleContext + parser antlr.Parser +} + +func NewEmptyPrimaryContext() *PrimaryContext { + var p = new(PrimaryContext) + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1) + p.RuleIndex = QueryParserRULE_primary + return p +} + +func InitEmptyPrimaryContext(p *PrimaryContext) { + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1) + p.RuleIndex = QueryParserRULE_primary +} + +func (*PrimaryContext) IsPrimaryContext() {} + +func NewPrimaryContext(parser antlr.Parser, parent antlr.ParserRuleContext, invokingState int) *PrimaryContext { + var p = new(PrimaryContext) + + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, parent, invokingState) + + p.parser = parser + p.RuleIndex = QueryParserRULE_primary + + return p +} + +func (s *PrimaryContext) GetParser() antlr.Parser { return s.parser } + +func (s *PrimaryContext) Condition() IConditionContext { + var t antlr.RuleContext + for _, ctx := range s.GetChildren() { + if _, ok := ctx.(IConditionContext); ok { + t = ctx.(antlr.RuleContext) + break + } + } + + if t == nil { + return nil + } + + return t.(IConditionContext) +} + +func (s *PrimaryContext) Expression() IExpressionContext { + var t antlr.RuleContext + for _, ctx := range s.GetChildren() { + if _, ok := ctx.(IExpressionContext); ok { + t = ctx.(antlr.RuleContext) + break + } + } + + if t == nil { + return nil + } + + return t.(IExpressionContext) +} + +func (s *PrimaryContext) GetRuleContext() antlr.RuleContext { + return s +} + +func (s *PrimaryContext) ToStringTree(ruleNames []string, recog antlr.Recognizer) string { + return antlr.TreesStringTree(s, ruleNames, recog) +} + +func (s *PrimaryContext) EnterRule(listener antlr.ParseTreeListener) { + if listenerT, ok := listener.(QueryListener); ok { + listenerT.EnterPrimary(s) + } +} + +func (s *PrimaryContext) ExitRule(listener antlr.ParseTreeListener) { + if listenerT, ok := listener.(QueryListener); ok { + listenerT.ExitPrimary(s) + } +} + +func (p *QueryParser) Primary() (localctx IPrimaryContext) { + localctx = NewPrimaryContext(p, p.GetParserRuleContext(), p.GetState()) + p.EnterRule(localctx, 16, QueryParserRULE_primary) + p.SetState(79) + p.GetErrorHandler().Sync(p) + if p.HasError() { + goto errorExit + } + + switch p.GetTokenStream().LA(1) { + case QueryParserIDENTIFIER: + p.EnterOuterAlt(localctx, 1) + { + p.SetState(74) + p.Condition() + } + + case QueryParserT__6: + p.EnterOuterAlt(localctx, 2) + { + p.SetState(75) + p.Match(QueryParserT__6) + if p.HasError() { + // Recognition error - abort rule + goto errorExit + } + } + { + p.SetState(76) + p.Expression() + } + { + p.SetState(77) + p.Match(QueryParserT__7) + if p.HasError() { + // Recognition error - abort rule + goto errorExit + } + } + + default: + p.SetError(antlr.NewNoViableAltException(p, nil, nil, nil, nil, nil)) + goto errorExit + } + +errorExit: + if p.HasError() { + v := p.GetError() + localctx.SetException(v) + p.GetErrorHandler().ReportError(p, v) + p.GetErrorHandler().Recover(p, v) + p.SetError(nil) + } + p.ExitRule() + return localctx + goto errorExit // Trick to prevent compiler error if the label is not used +} + +// IConditionContext is an interface to support dynamic dispatch. +type IConditionContext interface { + antlr.ParserRuleContext + + // GetParser returns the parser. + GetParser() antlr.Parser + + // Getter signatures + Alias() IAliasContext + AllMethod_chain() []IMethod_chainContext + Method_chain(i int) IMethod_chainContext + Comparator() IComparatorContext + Value() IValueContext + Value_list() IValue_listContext + + // IsConditionContext differentiates from other interfaces. + IsConditionContext() +} + +type ConditionContext struct { + antlr.BaseParserRuleContext + parser antlr.Parser +} + +func NewEmptyConditionContext() *ConditionContext { + var p = new(ConditionContext) + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1) + p.RuleIndex = QueryParserRULE_condition + return p +} + +func InitEmptyConditionContext(p *ConditionContext) { + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1) + p.RuleIndex = QueryParserRULE_condition +} + +func (*ConditionContext) IsConditionContext() {} + +func NewConditionContext(parser antlr.Parser, parent antlr.ParserRuleContext, invokingState int) *ConditionContext { + var p = new(ConditionContext) + + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, parent, invokingState) + + p.parser = parser + p.RuleIndex = QueryParserRULE_condition + + return p +} + +func (s *ConditionContext) GetParser() antlr.Parser { return s.parser } + +func (s *ConditionContext) Alias() IAliasContext { + var t antlr.RuleContext + for _, ctx := range s.GetChildren() { + if _, ok := ctx.(IAliasContext); ok { + t = ctx.(antlr.RuleContext) + break + } + } + + if t == nil { + return nil + } + + return t.(IAliasContext) +} + +func (s *ConditionContext) AllMethod_chain() []IMethod_chainContext { + children := s.GetChildren() + len := 0 + for _, ctx := range children { + if _, ok := ctx.(IMethod_chainContext); ok { + len++ + } + } + + tst := make([]IMethod_chainContext, len) + i := 0 + for _, ctx := range children { + if t, ok := ctx.(IMethod_chainContext); ok { + tst[i] = t.(IMethod_chainContext) + i++ + } + } + + return tst +} + +func (s *ConditionContext) Method_chain(i int) IMethod_chainContext { + var t antlr.RuleContext + j := 0 + for _, ctx := range s.GetChildren() { + if _, ok := ctx.(IMethod_chainContext); ok { + if j == i { + t = ctx.(antlr.RuleContext) + break + } + j++ + } + } + + if t == nil { + return nil + } + + return t.(IMethod_chainContext) +} + +func (s *ConditionContext) Comparator() IComparatorContext { + var t antlr.RuleContext + for _, ctx := range s.GetChildren() { + if _, ok := ctx.(IComparatorContext); ok { + t = ctx.(antlr.RuleContext) + break + } + } + + if t == nil { + return nil + } + + return t.(IComparatorContext) +} + +func (s *ConditionContext) Value() IValueContext { + var t antlr.RuleContext + for _, ctx := range s.GetChildren() { + if _, ok := ctx.(IValueContext); ok { + t = ctx.(antlr.RuleContext) + break + } + } + + if t == nil { + return nil + } + + return t.(IValueContext) +} + +func (s *ConditionContext) Value_list() IValue_listContext { + var t antlr.RuleContext + for _, ctx := range s.GetChildren() { + if _, ok := ctx.(IValue_listContext); ok { + t = ctx.(antlr.RuleContext) + break + } + } + + if t == nil { + return nil + } + + return t.(IValue_listContext) +} + +func (s *ConditionContext) GetRuleContext() antlr.RuleContext { + return s +} + +func (s *ConditionContext) ToStringTree(ruleNames []string, recog antlr.Recognizer) string { + return antlr.TreesStringTree(s, ruleNames, recog) +} + +func (s *ConditionContext) EnterRule(listener antlr.ParseTreeListener) { + if listenerT, ok := listener.(QueryListener); ok { + listenerT.EnterCondition(s) + } +} + +func (s *ConditionContext) ExitRule(listener antlr.ParseTreeListener) { + if listenerT, ok := listener.(QueryListener); ok { + listenerT.ExitCondition(s) + } +} + +func (p *QueryParser) Condition() (localctx IConditionContext) { + localctx = NewConditionContext(p, p.GetParserRuleContext(), p.GetState()) + p.EnterRule(localctx, 18, QueryParserRULE_condition) + p.EnterOuterAlt(localctx, 1) + { + p.SetState(81) + p.Alias() + } + { + p.SetState(82) + p.Match(QueryParserT__8) + if p.HasError() { + // Recognition error - abort rule + goto errorExit + } + } + { + p.SetState(83) + p.Method_chain() + } + { + p.SetState(84) + p.Comparator() + } + p.SetState(91) + p.GetErrorHandler().Sync(p) + if p.HasError() { + goto errorExit + } + + switch p.GetTokenStream().LA(1) { + case QueryParserSTRING, QueryParserSTRING_WITH_WILDCARD, QueryParserNUMBER: + { + p.SetState(85) + p.Value() + } + + case QueryParserIDENTIFIER: + { + p.SetState(86) + p.Method_chain() + } + + case QueryParserT__6: + { + p.SetState(87) + p.Match(QueryParserT__6) + if p.HasError() { + // Recognition error - abort rule + goto errorExit + } + } + { + p.SetState(88) + p.Value_list() + } + { + p.SetState(89) + p.Match(QueryParserT__7) + if p.HasError() { + // Recognition error - abort rule + goto errorExit + } + } + + default: + p.SetError(antlr.NewNoViableAltException(p, nil, nil, nil, nil, nil)) + goto errorExit + } + +errorExit: + if p.HasError() { + v := p.GetError() + localctx.SetException(v) + p.GetErrorHandler().ReportError(p, v) + p.GetErrorHandler().Recover(p, v) + p.SetError(nil) + } + p.ExitRule() + return localctx + goto errorExit // Trick to prevent compiler error if the label is not used +} + +// IMethod_chainContext is an interface to support dynamic dispatch. +type IMethod_chainContext interface { + antlr.ParserRuleContext + + // GetParser returns the parser. + GetParser() antlr.Parser + + // Getter signatures + AllMethod_or_variable() []IMethod_or_variableContext + Method_or_variable(i int) IMethod_or_variableContext + + // IsMethod_chainContext differentiates from other interfaces. + IsMethod_chainContext() +} + +type Method_chainContext struct { + antlr.BaseParserRuleContext + parser antlr.Parser +} + +func NewEmptyMethod_chainContext() *Method_chainContext { + var p = new(Method_chainContext) + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1) + p.RuleIndex = QueryParserRULE_method_chain + return p +} + +func InitEmptyMethod_chainContext(p *Method_chainContext) { + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1) + p.RuleIndex = QueryParserRULE_method_chain +} + +func (*Method_chainContext) IsMethod_chainContext() {} + +func NewMethod_chainContext(parser antlr.Parser, parent antlr.ParserRuleContext, invokingState int) *Method_chainContext { + var p = new(Method_chainContext) + + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, parent, invokingState) + + p.parser = parser + p.RuleIndex = QueryParserRULE_method_chain + + return p +} + +func (s *Method_chainContext) GetParser() antlr.Parser { return s.parser } + +func (s *Method_chainContext) AllMethod_or_variable() []IMethod_or_variableContext { + children := s.GetChildren() + len := 0 + for _, ctx := range children { + if _, ok := ctx.(IMethod_or_variableContext); ok { + len++ + } + } + + tst := make([]IMethod_or_variableContext, len) + i := 0 + for _, ctx := range children { + if t, ok := ctx.(IMethod_or_variableContext); ok { + tst[i] = t.(IMethod_or_variableContext) + i++ + } + } + + return tst +} + +func (s *Method_chainContext) Method_or_variable(i int) IMethod_or_variableContext { + var t antlr.RuleContext + j := 0 + for _, ctx := range s.GetChildren() { + if _, ok := ctx.(IMethod_or_variableContext); ok { + if j == i { + t = ctx.(antlr.RuleContext) + break + } + j++ + } + } + + if t == nil { + return nil + } + + return t.(IMethod_or_variableContext) +} + +func (s *Method_chainContext) GetRuleContext() antlr.RuleContext { + return s +} + +func (s *Method_chainContext) ToStringTree(ruleNames []string, recog antlr.Recognizer) string { + return antlr.TreesStringTree(s, ruleNames, recog) +} + +func (s *Method_chainContext) EnterRule(listener antlr.ParseTreeListener) { + if listenerT, ok := listener.(QueryListener); ok { + listenerT.EnterMethod_chain(s) + } +} + +func (s *Method_chainContext) ExitRule(listener antlr.ParseTreeListener) { + if listenerT, ok := listener.(QueryListener); ok { + listenerT.ExitMethod_chain(s) + } +} + +func (p *QueryParser) Method_chain() (localctx IMethod_chainContext) { + localctx = NewMethod_chainContext(p, p.GetParserRuleContext(), p.GetState()) + p.EnterRule(localctx, 20, QueryParserRULE_method_chain) + var _la int + + p.EnterOuterAlt(localctx, 1) + { + p.SetState(93) + p.Method_or_variable() + } + p.SetState(98) + p.GetErrorHandler().Sync(p) + if p.HasError() { + goto errorExit + } + _la = p.GetTokenStream().LA(1) + + for _la == QueryParserT__8 { + { + p.SetState(94) + p.Match(QueryParserT__8) + if p.HasError() { + // Recognition error - abort rule + goto errorExit + } + } + { + p.SetState(95) + p.Method_or_variable() + } + + p.SetState(100) + p.GetErrorHandler().Sync(p) + if p.HasError() { + goto errorExit + } + _la = p.GetTokenStream().LA(1) + } + +errorExit: + if p.HasError() { + v := p.GetError() + localctx.SetException(v) + p.GetErrorHandler().ReportError(p, v) + p.GetErrorHandler().Recover(p, v) + p.SetError(nil) + } + p.ExitRule() + return localctx + goto errorExit // Trick to prevent compiler error if the label is not used +} + +// IMethod_or_variableContext is an interface to support dynamic dispatch. +type IMethod_or_variableContext interface { + antlr.ParserRuleContext + + // GetParser returns the parser. + GetParser() antlr.Parser + + // Getter signatures + Method() IMethodContext + Variable() IVariableContext + + // IsMethod_or_variableContext differentiates from other interfaces. + IsMethod_or_variableContext() +} + +type Method_or_variableContext struct { + antlr.BaseParserRuleContext + parser antlr.Parser +} + +func NewEmptyMethod_or_variableContext() *Method_or_variableContext { + var p = new(Method_or_variableContext) + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1) + p.RuleIndex = QueryParserRULE_method_or_variable + return p +} + +func InitEmptyMethod_or_variableContext(p *Method_or_variableContext) { + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1) + p.RuleIndex = QueryParserRULE_method_or_variable +} + +func (*Method_or_variableContext) IsMethod_or_variableContext() {} + +func NewMethod_or_variableContext(parser antlr.Parser, parent antlr.ParserRuleContext, invokingState int) *Method_or_variableContext { + var p = new(Method_or_variableContext) + + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, parent, invokingState) + + p.parser = parser + p.RuleIndex = QueryParserRULE_method_or_variable + + return p +} + +func (s *Method_or_variableContext) GetParser() antlr.Parser { return s.parser } + +func (s *Method_or_variableContext) Method() IMethodContext { + var t antlr.RuleContext + for _, ctx := range s.GetChildren() { + if _, ok := ctx.(IMethodContext); ok { + t = ctx.(antlr.RuleContext) + break + } + } + + if t == nil { + return nil + } + + return t.(IMethodContext) +} + +func (s *Method_or_variableContext) Variable() IVariableContext { + var t antlr.RuleContext + for _, ctx := range s.GetChildren() { + if _, ok := ctx.(IVariableContext); ok { + t = ctx.(antlr.RuleContext) + break + } + } + + if t == nil { + return nil + } + + return t.(IVariableContext) +} + +func (s *Method_or_variableContext) GetRuleContext() antlr.RuleContext { + return s +} + +func (s *Method_or_variableContext) ToStringTree(ruleNames []string, recog antlr.Recognizer) string { + return antlr.TreesStringTree(s, ruleNames, recog) +} + +func (s *Method_or_variableContext) EnterRule(listener antlr.ParseTreeListener) { + if listenerT, ok := listener.(QueryListener); ok { + listenerT.EnterMethod_or_variable(s) + } +} + +func (s *Method_or_variableContext) ExitRule(listener antlr.ParseTreeListener) { + if listenerT, ok := listener.(QueryListener); ok { + listenerT.ExitMethod_or_variable(s) + } +} + +func (p *QueryParser) Method_or_variable() (localctx IMethod_or_variableContext) { + localctx = NewMethod_or_variableContext(p, p.GetParserRuleContext(), p.GetState()) + p.EnterRule(localctx, 22, QueryParserRULE_method_or_variable) + p.SetState(103) + p.GetErrorHandler().Sync(p) + if p.HasError() { + goto errorExit + } + + switch p.GetInterpreter().AdaptivePredict(p.BaseParser, p.GetTokenStream(), 7, p.GetParserRuleContext()) { + case 1: + p.EnterOuterAlt(localctx, 1) + { + p.SetState(101) + p.Method() + } + + case 2: + p.EnterOuterAlt(localctx, 2) + { + p.SetState(102) + p.Variable() + } + + case antlr.ATNInvalidAltNumber: + goto errorExit + } + +errorExit: + if p.HasError() { + v := p.GetError() + localctx.SetException(v) + p.GetErrorHandler().ReportError(p, v) + p.GetErrorHandler().Recover(p, v) + p.SetError(nil) + } + p.ExitRule() + return localctx + goto errorExit // Trick to prevent compiler error if the label is not used +} + +// IMethodContext is an interface to support dynamic dispatch. +type IMethodContext interface { + antlr.ParserRuleContext + + // GetParser returns the parser. + GetParser() antlr.Parser + + // Getter signatures + IDENTIFIER() antlr.TerminalNode + + // IsMethodContext differentiates from other interfaces. + IsMethodContext() +} + +type MethodContext struct { + antlr.BaseParserRuleContext + parser antlr.Parser +} + +func NewEmptyMethodContext() *MethodContext { + var p = new(MethodContext) + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1) + p.RuleIndex = QueryParserRULE_method + return p +} + +func InitEmptyMethodContext(p *MethodContext) { + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1) + p.RuleIndex = QueryParserRULE_method +} + +func (*MethodContext) IsMethodContext() {} + +func NewMethodContext(parser antlr.Parser, parent antlr.ParserRuleContext, invokingState int) *MethodContext { + var p = new(MethodContext) + + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, parent, invokingState) + + p.parser = parser + p.RuleIndex = QueryParserRULE_method + + return p +} + +func (s *MethodContext) GetParser() antlr.Parser { return s.parser } + +func (s *MethodContext) IDENTIFIER() antlr.TerminalNode { + return s.GetToken(QueryParserIDENTIFIER, 0) +} + +func (s *MethodContext) GetRuleContext() antlr.RuleContext { + return s +} + +func (s *MethodContext) ToStringTree(ruleNames []string, recog antlr.Recognizer) string { + return antlr.TreesStringTree(s, ruleNames, recog) +} + +func (s *MethodContext) EnterRule(listener antlr.ParseTreeListener) { + if listenerT, ok := listener.(QueryListener); ok { + listenerT.EnterMethod(s) + } +} + +func (s *MethodContext) ExitRule(listener antlr.ParseTreeListener) { + if listenerT, ok := listener.(QueryListener); ok { + listenerT.ExitMethod(s) + } +} + +func (p *QueryParser) Method() (localctx IMethodContext) { + localctx = NewMethodContext(p, p.GetParserRuleContext(), p.GetState()) + p.EnterRule(localctx, 24, QueryParserRULE_method) + p.EnterOuterAlt(localctx, 1) + { + p.SetState(105) + p.Match(QueryParserIDENTIFIER) + if p.HasError() { + // Recognition error - abort rule + goto errorExit + } + } + { + p.SetState(106) + p.Match(QueryParserT__6) + if p.HasError() { + // Recognition error - abort rule + goto errorExit + } + } + { + p.SetState(107) + p.Match(QueryParserT__7) + if p.HasError() { + // Recognition error - abort rule + goto errorExit + } + } + +errorExit: + if p.HasError() { + v := p.GetError() + localctx.SetException(v) + p.GetErrorHandler().ReportError(p, v) + p.GetErrorHandler().Recover(p, v) + p.SetError(nil) + } + p.ExitRule() + return localctx + goto errorExit // Trick to prevent compiler error if the label is not used +} + +// IVariableContext is an interface to support dynamic dispatch. +type IVariableContext interface { + antlr.ParserRuleContext + + // GetParser returns the parser. + GetParser() antlr.Parser + + // Getter signatures + IDENTIFIER() antlr.TerminalNode + + // IsVariableContext differentiates from other interfaces. + IsVariableContext() +} + +type VariableContext struct { + antlr.BaseParserRuleContext + parser antlr.Parser +} + +func NewEmptyVariableContext() *VariableContext { + var p = new(VariableContext) + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1) + p.RuleIndex = QueryParserRULE_variable + return p +} + +func InitEmptyVariableContext(p *VariableContext) { + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1) + p.RuleIndex = QueryParserRULE_variable +} + +func (*VariableContext) IsVariableContext() {} + +func NewVariableContext(parser antlr.Parser, parent antlr.ParserRuleContext, invokingState int) *VariableContext { + var p = new(VariableContext) + + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, parent, invokingState) + + p.parser = parser + p.RuleIndex = QueryParserRULE_variable + + return p +} + +func (s *VariableContext) GetParser() antlr.Parser { return s.parser } + +func (s *VariableContext) IDENTIFIER() antlr.TerminalNode { + return s.GetToken(QueryParserIDENTIFIER, 0) +} + +func (s *VariableContext) GetRuleContext() antlr.RuleContext { + return s +} + +func (s *VariableContext) ToStringTree(ruleNames []string, recog antlr.Recognizer) string { + return antlr.TreesStringTree(s, ruleNames, recog) +} + +func (s *VariableContext) EnterRule(listener antlr.ParseTreeListener) { + if listenerT, ok := listener.(QueryListener); ok { + listenerT.EnterVariable(s) + } +} + +func (s *VariableContext) ExitRule(listener antlr.ParseTreeListener) { + if listenerT, ok := listener.(QueryListener); ok { + listenerT.ExitVariable(s) + } +} + +func (p *QueryParser) Variable() (localctx IVariableContext) { + localctx = NewVariableContext(p, p.GetParserRuleContext(), p.GetState()) + p.EnterRule(localctx, 26, QueryParserRULE_variable) + p.EnterOuterAlt(localctx, 1) + { + p.SetState(109) + p.Match(QueryParserIDENTIFIER) + if p.HasError() { + // Recognition error - abort rule + goto errorExit + } + } + +errorExit: + if p.HasError() { + v := p.GetError() + localctx.SetException(v) + p.GetErrorHandler().ReportError(p, v) + p.GetErrorHandler().Recover(p, v) + p.SetError(nil) + } + p.ExitRule() + return localctx + goto errorExit // Trick to prevent compiler error if the label is not used +} + +// IComparatorContext is an interface to support dynamic dispatch. +type IComparatorContext interface { + antlr.ParserRuleContext + + // GetParser returns the parser. + GetParser() antlr.Parser + // IsComparatorContext differentiates from other interfaces. + IsComparatorContext() +} + +type ComparatorContext struct { + antlr.BaseParserRuleContext + parser antlr.Parser +} + +func NewEmptyComparatorContext() *ComparatorContext { + var p = new(ComparatorContext) + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1) + p.RuleIndex = QueryParserRULE_comparator + return p +} + +func InitEmptyComparatorContext(p *ComparatorContext) { + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1) + p.RuleIndex = QueryParserRULE_comparator +} + +func (*ComparatorContext) IsComparatorContext() {} + +func NewComparatorContext(parser antlr.Parser, parent antlr.ParserRuleContext, invokingState int) *ComparatorContext { + var p = new(ComparatorContext) + + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, parent, invokingState) + + p.parser = parser + p.RuleIndex = QueryParserRULE_comparator + + return p +} + +func (s *ComparatorContext) GetParser() antlr.Parser { return s.parser } +func (s *ComparatorContext) GetRuleContext() antlr.RuleContext { + return s +} + +func (s *ComparatorContext) ToStringTree(ruleNames []string, recog antlr.Recognizer) string { + return antlr.TreesStringTree(s, ruleNames, recog) +} + +func (s *ComparatorContext) EnterRule(listener antlr.ParseTreeListener) { + if listenerT, ok := listener.(QueryListener); ok { + listenerT.EnterComparator(s) + } +} + +func (s *ComparatorContext) ExitRule(listener antlr.ParseTreeListener) { + if listenerT, ok := listener.(QueryListener); ok { + listenerT.ExitComparator(s) + } +} + +func (p *QueryParser) Comparator() (localctx IComparatorContext) { + localctx = NewComparatorContext(p, p.GetParserRuleContext(), p.GetState()) + p.EnterRule(localctx, 28, QueryParserRULE_comparator) + var _la int + + p.EnterOuterAlt(localctx, 1) + { + p.SetState(111) + _la = p.GetTokenStream().LA(1) + + if !((int64(_la) & ^0x3f) == 0 && ((int64(1)<<_la)&261120) != 0) { + p.GetErrorHandler().RecoverInline(p) + } else { + p.GetErrorHandler().ReportMatch(p) + p.Consume() + } + } + +errorExit: + if p.HasError() { + v := p.GetError() + localctx.SetException(v) + p.GetErrorHandler().ReportError(p, v) + p.GetErrorHandler().Recover(p, v) + p.SetError(nil) + } + p.ExitRule() + return localctx + goto errorExit // Trick to prevent compiler error if the label is not used +} + +// IValueContext is an interface to support dynamic dispatch. +type IValueContext interface { + antlr.ParserRuleContext + + // GetParser returns the parser. + GetParser() antlr.Parser + + // Getter signatures + STRING() antlr.TerminalNode + NUMBER() antlr.TerminalNode + STRING_WITH_WILDCARD() antlr.TerminalNode + + // IsValueContext differentiates from other interfaces. + IsValueContext() +} + +type ValueContext struct { + antlr.BaseParserRuleContext + parser antlr.Parser +} + +func NewEmptyValueContext() *ValueContext { + var p = new(ValueContext) + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1) + p.RuleIndex = QueryParserRULE_value + return p +} + +func InitEmptyValueContext(p *ValueContext) { + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1) + p.RuleIndex = QueryParserRULE_value +} + +func (*ValueContext) IsValueContext() {} + +func NewValueContext(parser antlr.Parser, parent antlr.ParserRuleContext, invokingState int) *ValueContext { + var p = new(ValueContext) + + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, parent, invokingState) + + p.parser = parser + p.RuleIndex = QueryParserRULE_value + + return p +} + +func (s *ValueContext) GetParser() antlr.Parser { return s.parser } + +func (s *ValueContext) STRING() antlr.TerminalNode { + return s.GetToken(QueryParserSTRING, 0) +} + +func (s *ValueContext) NUMBER() antlr.TerminalNode { + return s.GetToken(QueryParserNUMBER, 0) +} + +func (s *ValueContext) STRING_WITH_WILDCARD() antlr.TerminalNode { + return s.GetToken(QueryParserSTRING_WITH_WILDCARD, 0) +} + +func (s *ValueContext) GetRuleContext() antlr.RuleContext { + return s +} + +func (s *ValueContext) ToStringTree(ruleNames []string, recog antlr.Recognizer) string { + return antlr.TreesStringTree(s, ruleNames, recog) +} + +func (s *ValueContext) EnterRule(listener antlr.ParseTreeListener) { + if listenerT, ok := listener.(QueryListener); ok { + listenerT.EnterValue(s) + } +} + +func (s *ValueContext) ExitRule(listener antlr.ParseTreeListener) { + if listenerT, ok := listener.(QueryListener); ok { + listenerT.ExitValue(s) + } +} + +func (p *QueryParser) Value() (localctx IValueContext) { + localctx = NewValueContext(p, p.GetParserRuleContext(), p.GetState()) + p.EnterRule(localctx, 30, QueryParserRULE_value) + var _la int + + p.EnterOuterAlt(localctx, 1) + { + p.SetState(113) + _la = p.GetTokenStream().LA(1) + + if !((int64(_la) & ^0x3f) == 0 && ((int64(1)<<_la)&1835008) != 0) { + p.GetErrorHandler().RecoverInline(p) + } else { + p.GetErrorHandler().ReportMatch(p) + p.Consume() + } + } + +errorExit: + if p.HasError() { + v := p.GetError() + localctx.SetException(v) + p.GetErrorHandler().ReportError(p, v) + p.GetErrorHandler().Recover(p, v) + p.SetError(nil) + } + p.ExitRule() + return localctx + goto errorExit // Trick to prevent compiler error if the label is not used +} + +// IValue_listContext is an interface to support dynamic dispatch. +type IValue_listContext interface { + antlr.ParserRuleContext + + // GetParser returns the parser. + GetParser() antlr.Parser + + // Getter signatures + AllValue() []IValueContext + Value(i int) IValueContext + + // IsValue_listContext differentiates from other interfaces. + IsValue_listContext() +} + +type Value_listContext struct { + antlr.BaseParserRuleContext + parser antlr.Parser +} + +func NewEmptyValue_listContext() *Value_listContext { + var p = new(Value_listContext) + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1) + p.RuleIndex = QueryParserRULE_value_list + return p +} + +func InitEmptyValue_listContext(p *Value_listContext) { + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1) + p.RuleIndex = QueryParserRULE_value_list +} + +func (*Value_listContext) IsValue_listContext() {} + +func NewValue_listContext(parser antlr.Parser, parent antlr.ParserRuleContext, invokingState int) *Value_listContext { + var p = new(Value_listContext) + + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, parent, invokingState) + + p.parser = parser + p.RuleIndex = QueryParserRULE_value_list + + return p +} + +func (s *Value_listContext) GetParser() antlr.Parser { return s.parser } + +func (s *Value_listContext) AllValue() []IValueContext { + children := s.GetChildren() + len := 0 + for _, ctx := range children { + if _, ok := ctx.(IValueContext); ok { + len++ + } + } + + tst := make([]IValueContext, len) + i := 0 + for _, ctx := range children { + if t, ok := ctx.(IValueContext); ok { + tst[i] = t.(IValueContext) + i++ + } + } + + return tst +} + +func (s *Value_listContext) Value(i int) IValueContext { + var t antlr.RuleContext + j := 0 + for _, ctx := range s.GetChildren() { + if _, ok := ctx.(IValueContext); ok { + if j == i { + t = ctx.(antlr.RuleContext) + break + } + j++ + } + } + + if t == nil { + return nil + } + + return t.(IValueContext) +} + +func (s *Value_listContext) GetRuleContext() antlr.RuleContext { + return s +} + +func (s *Value_listContext) ToStringTree(ruleNames []string, recog antlr.Recognizer) string { + return antlr.TreesStringTree(s, ruleNames, recog) +} + +func (s *Value_listContext) EnterRule(listener antlr.ParseTreeListener) { + if listenerT, ok := listener.(QueryListener); ok { + listenerT.EnterValue_list(s) + } +} + +func (s *Value_listContext) ExitRule(listener antlr.ParseTreeListener) { + if listenerT, ok := listener.(QueryListener); ok { + listenerT.ExitValue_list(s) + } +} + +func (p *QueryParser) Value_list() (localctx IValue_listContext) { + localctx = NewValue_listContext(p, p.GetParserRuleContext(), p.GetState()) + p.EnterRule(localctx, 32, QueryParserRULE_value_list) + var _la int + + p.EnterOuterAlt(localctx, 1) + { + p.SetState(115) + p.Value() + } + p.SetState(120) + p.GetErrorHandler().Sync(p) + if p.HasError() { + goto errorExit + } + _la = p.GetTokenStream().LA(1) + + for _la == QueryParserT__2 { + { + p.SetState(116) + p.Match(QueryParserT__2) + if p.HasError() { + // Recognition error - abort rule + goto errorExit + } + } + { + p.SetState(117) + p.Value() + } + + p.SetState(122) + p.GetErrorHandler().Sync(p) + if p.HasError() { + goto errorExit + } + _la = p.GetTokenStream().LA(1) + } + +errorExit: + if p.HasError() { + v := p.GetError() + localctx.SetException(v) + p.GetErrorHandler().ReportError(p, v) + p.GetErrorHandler().Recover(p, v) + p.SetError(nil) + } + p.ExitRule() + return localctx + goto errorExit // Trick to prevent compiler error if the label is not used +} diff --git a/sourcecode-parser/api.go b/sourcecode-parser/api.go deleted file mode 100644 index e12735c..0000000 --- a/sourcecode-parser/api.go +++ /dev/null @@ -1,50 +0,0 @@ -// api.go - -package main - -import ( - "encoding/json" - "net/http" -) - -func StartServer(graph *CodeGraph) { - http.HandleFunc("/nodes", func(w http.ResponseWriter, _ *http.Request) { - // For simplicity, let's return all nodes. You can add query params to filter nodes. - err := json.NewEncoder(w).Encode(graph.Nodes) - if err != nil { - return - } - }) - - http.HandleFunc("/source-sink-analysis", func(w http.ResponseWriter, r *http.Request) { - query := r.URL.Query() - sourceMethod := query.Get("sourceMethod") - sinkMethod := query.Get("sinkMethod") - - if sourceMethod == "" || sinkMethod == "" { - http.Error(w, "sinkMethod and sourceMethod query parameters are required", http.StatusBadRequest) - return - } - - result := AnalyzeSourceSinkPatterns(graph, sourceMethod, sinkMethod) - // Return the result as JSON - // set json content type - w.Header().Set("Content-Type", "application/json") - err := json.NewEncoder(w).Encode(result) - if err != nil { - return - } - }) - - // create a http handler to respond with index.html file content - http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { - // Read the index.html file from html directory - http.ServeFile(w, r, "html/index.html") - }) - - //nolint:all - err := http.ListenAndServe(":8080", nil) - if err != nil { - return - } -} diff --git a/sourcecode-parser/construct.go b/sourcecode-parser/construct.go index 0a0a074..192be95 100644 --- a/sourcecode-parser/construct.go +++ b/sourcecode-parser/construct.go @@ -9,11 +9,13 @@ import ( "os" "path/filepath" "strings" + "sync" + "time" "github.com/shivasurya/code-pathfinder/sourcecode-parser/model" + "github.com/smacker/go-tree-sitter/java" sitter "github.com/smacker/go-tree-sitter" - "github.com/smacker/go-tree-sitter/java" //nolint:all ) @@ -99,6 +101,7 @@ func isJavaSourceFile(filename string) bool { return filepath.Ext(filename) == ".java" } +//nolint:all func hasAccess(node *sitter.Node, variableName string, sourceCode []byte) bool { if node == nil { return false @@ -395,7 +398,8 @@ func buildGraphFromAST(node *sitter.Node, sourceCode []byte, graph *CodeGraph, c } if node.Type() == "local_variable_declaration" { scope = "local" - hasAccessValue = hasAccess(node.NextSibling(), variableName, sourceCode) + //nolint:all + // hasAccessValue = hasAccess(node.NextSibling(), variableName, sourceCode) } else { scope = "field" } @@ -508,7 +512,10 @@ func extractMethodName(node *sitter.Node, sourceCode []byte, filepath string) (s func getFiles(directory string) ([]string, error) { var files []string - err := filepath.Walk(directory, func(path string, info os.FileInfo, _ error) error { + err := filepath.Walk(directory, func(path string, info os.FileInfo, err error) error { + if err != nil { + return err + } if !info.IsDir() { // append only java files if filepath.Ext(path) == ".java" { @@ -529,45 +536,123 @@ func readFile(path string) ([]byte, error) { } func Initialize(directory string) *CodeGraph { - // Initialize the parser - parser := sitter.NewParser() - defer parser.Close() - - // Set the language (Java in this case) - parser.SetLanguage(java.GetLanguage()) - codeGraph := NewCodeGraph() + // record start time + start := time.Now() files, err := getFiles(directory) if err != nil { //nolint:all - log.Fatal(err) + log.Println("Directory not found:", err) + return codeGraph } - for _, file := range files { - sourceCode, err := readFile(file) - if err != nil { - log.Fatal(err) - } - // Parse the source code - tree, err := parser.ParseCtx(context.TODO(), nil, sourceCode) - if err != nil { - log.Fatal(err) - } - //nolint:all - defer tree.Close() - // TODO: Merge the tree into a single root node - // TODO: normalize the class name without duplication of class, method names + totalFiles := len(files) + numWorkers := 5 // Number of concurrent workers + fileChan := make(chan string, totalFiles) + resultChan := make(chan *CodeGraph, totalFiles) + statusChan := make(chan string, numWorkers) + progressChan := make(chan int, totalFiles) + var wg sync.WaitGroup + + // Worker function + worker := func(workerID int) { + // Initialize the parser for each worker + parser := sitter.NewParser() + defer parser.Close() + + // Set the language (Java in this case) + parser.SetLanguage(java.GetLanguage()) + + for file := range fileChan { + fileName := filepath.Base(file) + statusChan <- fmt.Sprintf("\033[32mWorker %d ....... Reading and parsing code %s\033[0m", workerID, fileName) + sourceCode, err := readFile(file) + if err != nil { + log.Println("File not found:", err) + continue + } + // Parse the source code + tree, err := parser.ParseCtx(context.TODO(), nil, sourceCode) + if err != nil { + log.Println("Error parsing file:", err) + continue + } + //nolint:all + defer tree.Close() - rootNode := tree.RootNode() + rootNode := tree.RootNode() + localGraph := NewCodeGraph() + statusChan <- fmt.Sprintf("\033[32mWorker %d ....... Building graph and traversing code %s\033[0m", workerID, fileName) + buildGraphFromAST(rootNode, sourceCode, localGraph, nil, file) + statusChan <- fmt.Sprintf("\033[32mWorker %d ....... Done processing file %s\033[0m", workerID, fileName) - buildGraphFromAST(rootNode, sourceCode, codeGraph, nil, file) + resultChan <- localGraph + progressChan <- 1 + } + wg.Done() } - //nolint:all - // log.Println("Graph built successfully:", codeGraph) + + // Start workers + wg.Add(numWorkers) + for i := 0; i < numWorkers; i++ { + go worker(i + 1) + } + + // Send files to workers + for _, file := range files { + fileChan <- file + } + close(fileChan) + + // Status updater + go func() { + statusLines := make([]string, numWorkers) + progress := 0 + for { + select { + case status, ok := <-statusChan: + if !ok { + return + } + workerID := int(status[12] - '0') + statusLines[workerID-1] = status + case _, ok := <-progressChan: + if !ok { + return + } + progress++ + } + fmt.Print("\033[H\033[J") // Clear the screen + for _, line := range statusLines { + fmt.Println(line) + } + fmt.Printf("Progress: %d%%\n", (progress*100)/totalFiles) + } + }() + + // Wait for all workers to finish + go func() { + wg.Wait() + close(resultChan) + close(statusChan) + close(progressChan) + }() + + // Collect results + for localGraph := range resultChan { + for _, node := range localGraph.Nodes { + codeGraph.AddNode(node) + } + for _, edge := range localGraph.Edges { + codeGraph.AddEdge(edge.From, edge.To) + } + } + + end := time.Now() + elapsed := end.Sub(start) + log.Println("Elapsed time: ", elapsed) log.Println("Graph built successfully") - //nolint:all - // go StartServer(codeGraph) - // select {} + return codeGraph } diff --git a/sourcecode-parser/go.mod b/sourcecode-parser/go.mod index 1dcf045..80328f8 100644 --- a/sourcecode-parser/go.mod +++ b/sourcecode-parser/go.mod @@ -1,11 +1,14 @@ module github.com/shivasurya/code-pathfinder/sourcecode-parser -go 1.20 +go 1.22.0 require github.com/smacker/go-tree-sitter v0.0.0-20240625050157-a31a98a7c0f6 -require queryparser v0.0.0-00010101000000-000000000000 +require github.com/antlr4-go/antlr/v4 v4.13.1 -require github.com/jedib0t/go-pretty/v6 v6.5.9 // indirect +require github.com/stretchr/testify v1.9.0 // indirect -replace queryparser => ./queryparser +require ( + github.com/expr-lang/expr v1.16.9 // indirect + golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 // indirect +) diff --git a/sourcecode-parser/go.sum b/sourcecode-parser/go.sum index 5906dfc..7342dd8 100644 --- a/sourcecode-parser/go.sum +++ b/sourcecode-parser/go.sum @@ -1,23 +1,22 @@ +github.com/antlr4-go/antlr/v4 v4.13.1 h1:SqQKkuVZ+zWkMMNkjy5FZe5mr5WURWnlpmOuzYWrPrQ= +github.com/antlr4-go/antlr/v4 v4.13.1/go.mod h1:GKmUxMtwp6ZgGwZSva4eWPC5mS6vUAmOABFgjdkM7Nw= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/jedib0t/go-pretty/v6 v6.5.9 h1:ACteMBRrrmm1gMsXe9PSTOClQ63IXDUt03H5U+UV8OU= -github.com/jedib0t/go-pretty/v6 v6.5.9/go.mod h1:zbn98qrYlh95FIhwwsbIip0LYpwSG8SUOScs+v9/t0E= -github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U= -github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= +github.com/expr-lang/expr v1.16.9 h1:WUAzmR0JNI9JCiF0/ewwHB1gmcGw5wW7nWt8gc6PpCI= +github.com/expr-lang/expr v1.16.9/go.mod h1:8/vRC7+7HBzESEqt5kKpYXxrxkr31SaO8r40VO/1IT4= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= -github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/smacker/go-tree-sitter v0.0.0-20240625050157-a31a98a7c0f6 h1:mtD4ESyObQZnRVxHFcaYp2d7jMBDa4WJRXSB1Vszj+A= github.com/smacker/go-tree-sitter v0.0.0-20240625050157-a31a98a7c0f6/go.mod h1:q99oHDsbP0xRwmn7Vmob8gbSMNyvJ83OauXPSuHQuKE= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.4/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= -golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y= -golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 h1:2dVuKD2vS7b0QIHQbpyTISPd0LeHDbnYEryqj5Q1ug8= +golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= diff --git a/sourcecode-parser/go.work b/sourcecode-parser/go.work index 9d9d8bd..96b89a3 100644 --- a/sourcecode-parser/go.work +++ b/sourcecode-parser/go.work @@ -1,6 +1,3 @@ -go 1.21 +go 1.22.0 -use ( - . - queryparser -) \ No newline at end of file +use . diff --git a/sourcecode-parser/go.work.sum b/sourcecode-parser/go.work.sum index 0941d28..26167c6 100644 --- a/sourcecode-parser/go.work.sum +++ b/sourcecode-parser/go.work.sum @@ -1,17 +1,26 @@ github.com/felixge/fgprof v0.9.3 h1:VvyZxILNuCiUCSXtPtYmmtGvb65nqXh2QFWc0Wpf2/g= github.com/felixge/fgprof v0.9.3/go.mod h1:RdbpDgzqYVh/T9fPELJyV7EYJuHB55UTEULNun8eiPw= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/pprof v0.0.0-20211214055906-6f57359322fd h1:1FjCyPC+syAzJ5/2S8fqdZK1R22vvA0J7JZKcuOIQ7Y= github.com/google/pprof v0.0.0-20211214055906-6f57359322fd/go.mod h1:KgnwoLYCZ8IQu3XUZ8Nc/bM9CCZFOyjUNOSygVozoDg= -github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U= -github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/pkg/profile v1.7.0 h1:hnbDkaNWPCLMO9wGLdBFTIZvzDrDfBM2072E1S9gJkA= github.com/pkg/profile v1.7.0/go.mod h1:8Uer0jas47ZQMJ7VD+OHknK4YDY07LPUC6dEvqDjvNo= -github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= -github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/stretchr/objx v0.4.0 h1:M2gUjqZET1qApGOWNSnZ49BAIMX4F/1plDv3+l31EJ4= -github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= -golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y= -golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= +golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA= +golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/mod v0.19.0 h1:fEdghXQSo20giMthA7cd28ZC+jts4amQ3YMXiP5oMQ8= +golang.org/x/mod v0.19.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= +golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/term v0.17.0 h1:mkTF7LCd6WGJNL3K1Ad7kwxNfYAW6a8a8QqtMblp/4U= golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= +golang.org/x/tools v0.21.0 h1:qc0xYgIbsSDt9EyWz05J5wfa7LOVW0YTLOXrqdLAWIw= +golang.org/x/tools v0.21.0/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= +golang.org/x/tools v0.23.0 h1:SGsXPZ+2l4JsgaCKkx+FQ9YZ5XEtA1GZYuoDjenLjvg= +golang.org/x/tools v0.23.0/go.mod h1:pnu6ufv6vQkll6szChhK3C3L/ruaIv5eBeztNG8wtsI= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= diff --git a/sourcecode-parser/main.go b/sourcecode-parser/main.go index 952dd0c..599a937 100644 --- a/sourcecode-parser/main.go +++ b/sourcecode-parser/main.go @@ -6,64 +6,101 @@ import ( "flag" "fmt" "os" - "queryparser" + "strconv" "strings" - "github.com/jedib0t/go-pretty/v6/table" + parser "github.com/shivasurya/code-pathfinder/sourcecode-parser/antlr" ) -var ( - Version = "dev" - GitCommit = "none" +// Version is the current version of the application. +const ( + Version = "0.0.22" + GitCommit = "HEAD" ) +func main() { + // accept command line param optional path to source code + output := flag.String("output", "", "Supported output format: json") + outputFile := flag.String("output-file", "", "Output file path") + project := flag.String("project", "", "Project to analyze") + query := flag.String("query", "", "Query to execute") + stdin := flag.Bool("stdin", false, "Read query from stdin") + versionFlag := flag.Bool("version", false, "Print the version information and exit") + flag.Parse() + + if *versionFlag { + fmt.Printf("Version: %s\n", Version) + fmt.Printf("Git Commit: %s\n", GitCommit) + os.Exit(0) + } + + result, err := executeCLIQuery(*project, *query, *output, *stdin) + if err != nil { + fmt.Println(err) + } + if *outputFile != "" { + file, err := os.Create(*outputFile) + if err != nil { + fmt.Println("Error creating output file: ", err) + } + defer func(file *os.File) { + err := file.Close() + if err != nil { + fmt.Println("Error closing output file: ", err) + os.Exit(1) + } + }(file) + _, err = file.WriteString(result) + if err != nil { + fmt.Println("Error writing output file: ", err) + } + } else { + fmt.Println(result) + } +} + func processQuery(input string, graph *CodeGraph, output string) (string, error) { fmt.Println("Executing query: " + input) - lex := queryparser.NewLexer(input) - pars := queryparser.NewParser(lex) - query := pars.ParseQuery() - if query == nil { - return "", fmt.Errorf("failed to parse query: %v", pars.Errors()) - } - entities := QueryEntities(graph, query) + parsedQuery := parser.ParseQuery(input) + entities := QueryEntities(graph, parsedQuery) if output == "json" { // convert struct to query_results - queryResults, err := json.Marshal(entities) + results := []map[string]interface{}{} + for _, entity := range entities { + result := make(map[string]interface{}) + result["file"] = entity.File + result["line"] = entity.LineNumber + result["code"] = entity.CodeSnippet + results = append(results, result) + } + queryResults, err := json.Marshal(results) if err != nil { return "", fmt.Errorf("error processing query results: %w", err) } return string(queryResults), nil } - - t := table.NewWriter() - t.SetOutputMirror(os.Stdout) - t.AppendHeader(table.Row{"#", "File", "Line Number", "Type", "Name", "Code Snippet"}) - t.SetColumnConfigs([]table.ColumnConfig{ - { - Name: "File", - WidthMin: 6, - WidthMax: 40, - }, - { - Name: "Code Snippet", - WidthMin: 6, - WidthMax: 60, - }, - }) - for i, entity := range entities { - t.AppendRow([]interface{}{i + 1, entity.File, entity.LineNumber, entity.Type, entity.Name, entity.CodeSnippet}) - t.AppendSeparator() + result := "" + for _, entity := range entities { + // add blockquotes to string + result += entity.File + ":" + strconv.Itoa(int(entity.LineNumber)) + "\n" + result += "------------\n" + result += "> " + entity.CodeSnippet + "\n" + result += "------------" + result += "\n" } - t.SetStyle(table.StyleLight) - t.Render() - return "", nil + return result, nil } -func executeProject(project, query, output string, stdin bool) (string, error) { +func InitializeProject(project string) *CodeGraph { graph := NewCodeGraph() if project != "" { graph = Initialize(project) } + return graph +} + +func executeCLIQuery(project, query, output string, stdin bool) (string, error) { + graph := InitializeProject(project) if stdin { // read from stdin @@ -79,57 +116,45 @@ func executeProject(project, query, output string, stdin bool) (string, error) { if strings.HasPrefix(input, ":quit") { return "Okay, Bye!", nil } - _, err = processQuery(input, graph, output) + result, err := processQuery(input, graph, output) + fmt.Println(result) if err != nil { return "", fmt.Errorf("error processing query: %w", err) } } - } else if output != "" && query != "" { - return processQuery(query, graph, output) - } - return "", fmt.Errorf("output and query parameters are required") -} - -func main() { - // accept command line param optional path to source code - output := flag.String("output", "", "Supported output format: json") - outputFile := flag.String("output-file", "", "Output file path") - query := flag.String("query", "", "Query to execute") - project := flag.String("project", "", "Project to analyze") - stdin := flag.Bool("stdin", false, "Read query from stdin") - versionFlag := flag.Bool("version", false, "Print the version information and exit") - flag.Parse() - - if *versionFlag { - fmt.Printf("Version: %s\n", Version) - fmt.Printf("Git Commit: %s\n", GitCommit) - os.Exit(0) - } - - result, err := executeProject(*project, *query, *output, *stdin) - if err != nil { - fmt.Println(err) - return - } - if *outputFile != "" { - file, err := os.Create(*outputFile) - if err != nil { - fmt.Println("Error creating output file: ", err) - return - } - defer func(file *os.File) { - err := file.Close() - if err != nil { - fmt.Println("Error closing output file: ", err) - return - } - }(file) - _, err = file.WriteString(result) + } else { + // read from command line + result, err := processQuery(query, graph, output) if err != nil { - fmt.Println("Error writing output file: ", err) - return + return "", fmt.Errorf("error processing query: %w", err) } - } else { - fmt.Println(result) + return result, nil } } + +// func parseQueryWithExpr(inputQuery string) { +// +// // string replace "md." with "" +// expression = strings.Replace(expression, "md.", "", -1) +// fmt.Println(expression) +// env := map[string]interface{}{ +// "getName": func() string { +// return "onCreate" +// }, +// "getVisibility": func() string { +// return "public" +// }, +// "getReturnType": func() string { +// return "voids" +// }, +// } +// program, err := expr.Compile(expression, expr.Env(env)) +// if err != nil { +// fmt.Println(err) +// } +// output, err := expr.Run(program, env) +// if err != nil { +// fmt.Println(err) +// } +// fmt.Println(output) +//} diff --git a/sourcecode-parser/main_test.go b/sourcecode-parser/main_test.go index d9e93f8..10f9b5f 100644 --- a/sourcecode-parser/main_test.go +++ b/sourcecode-parser/main_test.go @@ -1,13 +1,15 @@ package main import ( + "encoding/json" + "fmt" "testing" ) func TestProcessQuery(t *testing.T) { graph := NewCodeGraph() output := "json" - input := "FIND variable_declaration WHERE visibility = 'private'" + input := "FIND method_declaration AS md WHERE md.GetVisibility() == \"public\"" result, err := processQuery(input, graph, output) if err != nil { @@ -21,20 +23,88 @@ func TestProcessQuery(t *testing.T) { } } -func TestExecuteProject(t *testing.T) { +func TestExecuteCLIQuery(t *testing.T) { // get project from command line project := "../test-src/" - query := "FIND variable_declaration WHERE visibility = 'private'" + queries := []string{ + `FIND method_declaration AS md WHERE md.getName() == "onCreate"`, + `FIND variable_declaration AS vd WHERE vd.getVisibility() == "private"`, + } output := "json" - result, err := executeProject(project, query, output, false) - if err != nil { - t.Errorf("Expected no error, got %v", err) + for _, query := range queries { + fmt.Println(query) + result, err := executeCLIQuery(project, query, output, false) + if err != nil { + t.Errorf("Expected no error for query %s, got %v", query, err) + } + var resultMap []map[string]interface{} + err = json.Unmarshal([]byte(result), &resultMap) + if len(resultMap) == 0 { + t.Errorf("Expected result to be non-empty for query %s", query) + } + if err != nil { + t.Errorf("Expected no error for query %s, got %v", query, err) + } + + // Here you can add assertions based on what you expect the result to be. + // This will depend on the specifics of your executeProject function. + if result == "" { + t.Errorf("Expected result to be non-empty for query %s", query) + } } +} - // Here you can add assertions based on what you expect the result to be. - // This will depend on the specifics of your executeProject function. - if result == "" { - t.Errorf("Expected result to be non-empty") +func TestInitializeProject(t *testing.T) { + tests := []struct { + name string + project string + want *CodeGraph + }{ + { + name: "Empty project", + project: "", + want: NewCodeGraph(), + }, + { + name: "Valid project", + project: "../test-src/", + want: Initialize("../test-src/"), + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got := InitializeProject(tt.project) + if got == nil { + t.Errorf("InitializeProject() returned nil") + } + if tt.project == "" && len(got.Nodes) != 0 { + t.Errorf("InitializeProject() with empty project should return empty graph") + } + if tt.project != "" && len(got.Nodes) == 0 { + t.Errorf("InitializeProject() with valid project should return non-empty graph") + } + }) + } +} + +func TestInitializeProjectWithInvalidPath(t *testing.T) { + invalidProject := "/path/to/nonexistent/project" + got := InitializeProject(invalidProject) + if got == nil || got.Nodes == nil { + t.Errorf("InitializeProject() with invalid path should return empty graph, not nil") + } else if len(got.Nodes) != 0 { + t.Errorf("InitializeProject() with invalid path should return empty graph") + } +} + +func TestInitializeProjectConsistency(t *testing.T) { + project := "../test-src/" + graph1 := InitializeProject(project) + graph2 := InitializeProject(project) + + if len(graph1.Nodes) != len(graph2.Nodes) { + t.Errorf("InitializeProject() should return consistent results for the same project") } } diff --git a/sourcecode-parser/query.go b/sourcecode-parser/query.go new file mode 100644 index 0000000..532b4a4 --- /dev/null +++ b/sourcecode-parser/query.go @@ -0,0 +1,240 @@ +package main + +import ( + "fmt" + + "github.com/expr-lang/expr" + parser "github.com/shivasurya/code-pathfinder/sourcecode-parser/antlr" +) + +type Env struct { + Node *GraphNode +} + +func (env *Env) GetVisibility() string { + return env.Node.Modifier +} + +func (env *Env) GetAnnotations() []string { + return env.Node.Annotation +} + +func (env *Env) GetReturnType() string { + return env.Node.ReturnType +} + +func (env *Env) GetName() string { + return env.Node.Name +} + +func (env *Env) GetArgumentTypes() []string { + return env.Node.MethodArgumentsType +} + +func (env *Env) GetArgumentNames() []string { + return env.Node.MethodArgumentsValue +} + +func (env *Env) GetSuperClass() string { + return env.Node.SuperClass +} + +func (env *Env) GetInterfaces() []string { + return env.Node.Interface +} + +func (env *Env) GetScope() string { + return env.Node.Scope +} + +func (env *Env) GetVariableValue() string { + return env.Node.VariableValue +} + +func (env *Env) GetVariableDataType() string { + return env.Node.DataType +} + +func (env *Env) GetThrowsTypes() []string { + return env.Node.ThrowsExceptions +} + +func (env *Env) HasAccess() bool { + return env.Node.hasAccess +} + +func (env *Env) IsJavaSourceFile() bool { + return env.Node.isJavaSourceFile +} + +func (env *Env) GetCommentAuthor() string { + if env.Node.JavaDoc != nil { + if env.Node.JavaDoc.Author != "" { + return env.Node.JavaDoc.Author + } + } + return "" +} + +func (env *Env) GetCommentSee() string { + if env.Node.JavaDoc != nil { + for _, docTag := range env.Node.JavaDoc.Tags { + if docTag.TagName == "see" && docTag.Text != "" { + return docTag.Text + } + } + } + return "" +} + +func (env *Env) GetCommentVersion() string { + if env.Node.JavaDoc != nil { + for _, docTag := range env.Node.JavaDoc.Tags { + if docTag.TagName == "version" && docTag.Text != "" { + return docTag.Text + } + } + } + return "" +} + +func (env *Env) GetCommentSince() string { + if env.Node.JavaDoc != nil { + for _, docTag := range env.Node.JavaDoc.Tags { + if docTag.TagName == "since" && docTag.Text != "" { + return docTag.Text + } + } + } + return "" +} + +func (env *Env) GetCommentParam() string { + if env.Node.JavaDoc != nil { + for _, docTag := range env.Node.JavaDoc.Tags { + if docTag.TagName == "param" && docTag.Text != "" { + return docTag.Text + } + } + } + return "" +} + +func (env *Env) GetCommentThrows() string { + if env.Node.JavaDoc != nil { + for _, docTag := range env.Node.JavaDoc.Tags { + if docTag.TagName == "throws" && docTag.Text != "" { + return docTag.Text + } + } + } + return "" +} + +func (env *Env) GetCommentReturn() string { + if env.Node.JavaDoc != nil { + for _, docTag := range env.Node.JavaDoc.Tags { + if docTag.TagName == "return" && docTag.Text != "" { + return docTag.Text + } + } + } + return "" +} + +func QueryEntities(graph *CodeGraph, query parser.Query) []*GraphNode { + result := make([]*GraphNode, 0) + + for _, node := range graph.Nodes { + for _, entity := range query.SelectList { + if entity.Entity == node.Type && FilterEntities(node, query) { + result = append(result, node) + } + } + } + return result +} + +func generateProxyEnv(node *GraphNode, query parser.Query) map[string]interface{} { + proxyenv := Env{Node: node} + methodDeclaration := "method_declaration" + classDeclaration := "class_declaration" + methodInvocation := "method_invocation" + variableDeclaration := "variable_declaration" + // print query select list + for _, entity := range query.SelectList { + switch entity.Entity { + case "method_declaration": + methodDeclaration = entity.Alias + case "class_declaration": + classDeclaration = entity.Alias + case "method_invocation": + methodInvocation = entity.Alias + case "variable_declaration": + variableDeclaration = entity.Alias + } + } + env := map[string]interface{}{ + "isJavaSourceFile": proxyenv.IsJavaSourceFile(), + "getCommentAuthor": proxyenv.GetCommentAuthor(), + "getCommentSee": proxyenv.GetCommentSee(), + "getCommentVersion": proxyenv.GetCommentVersion(), + "getCommentSince": proxyenv.GetCommentSince(), + "getCommentParam": proxyenv.GetCommentParam(), + "getCommentThrows": proxyenv.GetCommentThrows(), + "getCommentReturn": proxyenv.GetCommentReturn(), + methodDeclaration: map[string]interface{}{ + "getVisibility": proxyenv.GetVisibility(), + "getAnnotation": proxyenv.GetAnnotations(), + "getReturnType": proxyenv.GetReturnType, + "getName": proxyenv.GetName, + "getArgumentType": proxyenv.GetArgumentTypes(), + "getArgumentName": proxyenv.GetArgumentNames(), + "getInterface": proxyenv.GetInterfaces(), + "getThrowsType": proxyenv.GetThrowsTypes(), + }, + classDeclaration: map[string]interface{}{ + "getSuperClass": proxyenv.GetSuperClass, + "getName": proxyenv.GetName, + "getAnnotation": proxyenv.GetAnnotations(), + "getVisibility": proxyenv.GetVisibility, + "getInterface": proxyenv.GetInterfaces(), + }, + methodInvocation: map[string]interface{}{ + "getArgumentName": proxyenv.GetArgumentNames(), + "getName": proxyenv.GetName, + }, + variableDeclaration: map[string]interface{}{ + "getName": proxyenv.GetName, + "getVisibility": proxyenv.GetVisibility, + "getVariableValue": proxyenv.GetVariableValue, + "getVariableDataType": proxyenv.GetVariableDataType, + "getScope": proxyenv.GetScope(), + }, + } + return env +} + +func FilterEntities(node *GraphNode, query parser.Query) bool { + expression := query.Expression + if expression == "" { + return true + } + + env := generateProxyEnv(node, query) + + program, err := expr.Compile(expression, expr.Env(env)) + if err != nil { + fmt.Println("Error compiling expression: ", err) + return false + } + output, err := expr.Run(program, env) + if err != nil { + fmt.Println("Error evaluating expression: ", err) + return false + } + if output.(bool) { + return true + } + return false +} diff --git a/sourcecode-parser/queryparser/go.mod b/sourcecode-parser/queryparser/go.mod deleted file mode 100644 index 459e20b..0000000 --- a/sourcecode-parser/queryparser/go.mod +++ /dev/null @@ -1,3 +0,0 @@ -module queryparser - -go 1.20 diff --git a/sourcecode-parser/queryparser/lexer.go b/sourcecode-parser/queryparser/lexer.go deleted file mode 100644 index e53873a..0000000 --- a/sourcecode-parser/queryparser/lexer.go +++ /dev/null @@ -1,90 +0,0 @@ -package queryparser - -func NewLexer(input string) *Lexer { - return &Lexer{input: input} -} - -type Lexer struct { - input string - position int // current position in input (points to current char) - readPosition int // current reading position (after current char) - ch byte // current char under examination -} - -func (l *Lexer) readChar() { - if l.readPosition >= len(l.input) { - l.ch = 0 - } else { - l.ch = l.input[l.readPosition] - } - l.position = l.readPosition - l.readPosition++ -} - -func (l *Lexer) NextToken() Token { - var tok Token - l.skipWhitespace() - - switch l.ch { - case '=': - tok = Token{Type: OPERATOR, Literal: string(l.ch)} - case '!': - ch := l.ch - l.readChar() - tok = Token{Type: OPERATOR, Literal: string(ch) + string(l.ch)} - case '\'': - tok.Type = STRING - tok.Literal = l.readString() - case '(': - tok = Token{Type: LPAREN, Literal: string(l.ch)} - case ')': - tok = Token{Type: RPAREN, Literal: string(l.ch)} - case 0: // End of file or input - tok.Type = EOF - tok.Literal = "" - default: - if isLetter(l.ch) { - tok.Literal = l.readIdentifier() - tok.Type = LookupIdent(tok.Literal) - return tok - } else if l.ch == '"' { - tok.Type = STRING - tok.Literal = l.readString() - return tok - } else { - tok = Token{Type: ILLEGAL, Literal: string(l.ch)} - } - } - - l.readChar() - return tok -} - -func (l *Lexer) readIdentifier() string { - position := l.position - for isLetter(l.ch) { - l.readChar() - } - return l.input[position:l.position] -} - -func (l *Lexer) readString() string { - startPosition := l.position + 1 // skip the initial quote - for { - l.readChar() - if l.ch == '"' || l.ch == '\'' || l.ch == 0 { - break - } - } - return l.input[startPosition:l.position] -} - -func (l *Lexer) skipWhitespace() { - for l.ch == ' ' || l.ch == '\t' || l.ch == '\n' || l.ch == '\r' { - l.readChar() - } -} - -func isLetter(ch byte) bool { - return ('a' <= ch && ch <= 'z') || ('A' <= ch && ch <= 'Z') || ch == '_' -} diff --git a/sourcecode-parser/queryparser/parser.go b/sourcecode-parser/queryparser/parser.go deleted file mode 100644 index 4470fbb..0000000 --- a/sourcecode-parser/queryparser/parser.go +++ /dev/null @@ -1,178 +0,0 @@ -package queryparser - -import "fmt" - -type Parser struct { - l *Lexer - errors []string - curToken Token - peekToken Token -} - -func NewParser(l *Lexer) *Parser { - p := &Parser{l: l, errors: []string{}} - // Read two tokens, so curToken and peekToken are both set - p.nextToken() - p.nextToken() - return p -} - -func (p *Parser) Errors() []string { - return p.errors -} - -func (p *Parser) peekError(t TokenType) { - msg := fmt.Sprintf("expected next token to be %s, got %s instead", t, p.peekToken.Type) - p.errors = append(p.errors, msg) -} - -func (p *Parser) nextToken() { - p.peekToken = p.l.NextToken() - p.curToken = p.peekToken -} - -func (p *Parser) parseExpression() Expr { - expr := p.parseLogicalOr() // Start with the lowest precedence - return expr -} - -func (p *Parser) parseLogicalOr() Expr { - expr := p.parseLogicalAnd() - for p.curToken.Type == KEYWORD && p.peekToken.Literal == "OR" { - p.nextToken() - right := p.parseLogicalAnd() - expr = &BinaryExpr{ - Left: expr, - Op: "OR", - Right: right, - } - } - return expr -} - -func (p *Parser) parseLogicalAnd() Expr { - expr := p.parseGroup() - for p.curToken.Type == KEYWORD && p.peekToken.Literal == "AND" { - p.nextToken() - right := p.parseGroup() - expr = &BinaryExpr{ - Left: expr, - Op: "AND", - Right: right, - } - } - return expr -} - -func (p *Parser) parseGroup() Expr { - if p.curToken.Type == LPAREN { - p.nextToken() // Skip '(' - expr := p.parseExpression() // Parse expression within parentheses - if p.curToken.Type != RPAREN { - p.peekError(p.curToken.Type) - return nil - } - p.nextToken() // Skip ')' - return expr - } - return p.parseCondition() // Parse a basic condition -} - -func (p *Parser) parseCondition() *Condition { - if p.curToken.Type != IDENT { - p.peekError(IDENT) - return nil - } - - field := p.curToken.Literal - p.nextToken() - - if p.curToken.Type != OPERATOR { - p.peekError(OPERATOR) - return nil - } - - operator := p.curToken.Literal - p.nextToken() - - if p.curToken.Type != STRING && p.curToken.Type != IDENT { - p.peekError(STRING) - return nil - } - value := p.curToken.Literal - p.nextToken() // move past the value - - return &Condition{Field: field, Operator: operator, Value: value} -} - -type EvalContext interface { - GetValue(key string, val string) string // Retrieves a value based on a key, which helps in condition evaluation. -} - -type Expr interface { - Evaluate(ctx EvalContext) bool -} - -type BinaryExpr struct { - Left Expr - Right Expr - Op string -} - -func (p *Parser) ParseQuery() *Query { - // fmt.Printf("Current token: %s\n", p.curToken.Literal) // Debug output - - query := &Query{} - - if p.curToken.Type != KEYWORD || p.curToken.Literal != "FIND" { - p.peekError(KEYWORD) - return nil - } - - query.Operation = p.curToken.Literal - p.nextToken() - - if p.curToken.Type != IDENT { - p.peekError(IDENT) - return nil - } - - query.Entity = p.curToken.Literal - p.nextToken() - - if p.curToken.Type != KEYWORD || p.curToken.Literal != "WHERE" { - p.peekError(KEYWORD) - return nil - } - - p.nextToken() - expr := p.parseExpression() - if expr == nil { - // handle error or invalid expression - return nil - } - query.Conditions = expr - - return query -} - -func (b *BinaryExpr) Evaluate(ctx EvalContext) bool { - switch b.Op { - case "AND": - return b.Left.Evaluate(ctx) && b.Right.Evaluate(ctx) - case "OR": - return b.Left.Evaluate(ctx) || b.Right.Evaluate(ctx) - } - return false -} - -func (c *Condition) Evaluate(ctx EvalContext) bool { - fieldValue := ctx.GetValue(c.Field, c.Value) - switch c.Operator { - case "=": - return fieldValue == c.Value - case "!=": - return fieldValue != c.Value - } - return false -} diff --git a/sourcecode-parser/queryparser/tokenizer.go b/sourcecode-parser/queryparser/tokenizer.go deleted file mode 100644 index 6418611..0000000 --- a/sourcecode-parser/queryparser/tokenizer.go +++ /dev/null @@ -1,79 +0,0 @@ -package queryparser - -import "fmt" - -// Token represents a lexical token. -type TokenType int - -const ( - ILLEGAL TokenType = iota - EOF - WS - // Special tokens - IDENT // Identifiers - STRING // String literals - KEYWORD // Keywords such as FIND, WHERE - OPERATOR // Operators such as =, INCLUDES, MATCHES - LPAREN // Left parenthesis '(' - RPAREN -) - -type Token struct { - Type TokenType - Literal string -} - -type Node interface { - node() -} - -type Query struct { - Operation string - Entity string - Conditions Expr -} - -type Condition struct { - Field string - Operator string - Value string -} - -func (q Query) node() {} -func (c Condition) node() {} - -// Define keywords -var keywords = map[string]TokenType{ - "FIND": KEYWORD, - "WHERE": KEYWORD, - "AND": KEYWORD, - "OR": KEYWORD, -} - -func LookupIdent(ident string) TokenType { - if tok, ok := keywords[ident]; ok { - return tok - } - return IDENT -} - -func (t TokenType) String() string { - switch t { - case EOF: - return "EOF" - case IDENT: - return "IDENT" - case KEYWORD: - return "KEYWORD" - case STRING: - return "STRING" - case OPERATOR: - return "OPERATOR" - case WS: - return "WS" - case ILLEGAL: - return "ILLEGAL" - default: - return fmt.Sprintf("UNKNOWN(%d)", int(t)) - } -} diff --git a/sourcecode-parser/source_sink.go b/sourcecode-parser/source_sink.go index 91957d5..fbdd0bc 100644 --- a/sourcecode-parser/source_sink.go +++ b/sourcecode-parser/source_sink.go @@ -3,7 +3,6 @@ package main import ( "fmt" - "queryparser" ) type Result struct { @@ -64,154 +63,3 @@ func AnalyzeSourceSinkPatterns(graph *CodeGraph, sourceMethodName, sinkMethodNam // Return true if sourceNode is connected to sinkNode as a result of the DFS return Result{IsConnected: isConnected, SourceMethod: sourceNode.CodeSnippet, SinkMethod: sinkNode.CodeSnippet, SourceLine: sourceNode.LineNumber, SinkLine: sinkNode.LineNumber} } - -type GraphNodeContext struct { - Node *GraphNode -} - -// GetValue returns the value of a field in a GraphNode based on the key. -func (gnc *GraphNodeContext) GetValue(key, val string) string { - switch key { - case "visibility": - return gnc.Node.Modifier - case "annotation": - for _, annotation := range gnc.Node.Annotation { - if annotation == val { - return annotation - } - } - return "" - case "returntype": - return gnc.Node.ReturnType - case "name": - return gnc.Node.Name - case "argumentype": - // check value in MethodArgumentsType array - for i, arg := range gnc.Node.MethodArgumentsType { - if arg == val { - return gnc.Node.MethodArgumentsType[i] - } - } - return "" - case "argumentname": - // check value in MethodArgumentsValue array - for i, arg := range gnc.Node.MethodArgumentsValue { - if arg == val { - return gnc.Node.MethodArgumentsValue[i] - } - } - return "" - case "superclass": - return gnc.Node.SuperClass - case "interface": - // check value in Interface array - for i, iface := range gnc.Node.Interface { - if iface == val { - return gnc.Node.Interface[i] - } - } - return "" - case "scope": - return gnc.Node.Scope - case "variablevalue": - return gnc.Node.VariableValue - case "variabledatatype": - return gnc.Node.DataType - case "throwstype": - for i, arg := range gnc.Node.ThrowsExceptions { - if arg == val { - return gnc.Node.ThrowsExceptions[i] - } - } - return "" - case "has_access": - if gnc.Node.hasAccess { - return "true" - } - return "false" - case "is_java_source": - if gnc.Node.isJavaSourceFile { - return "true" - } - return "false" - case "comment_author": - if gnc.Node.JavaDoc != nil { - if gnc.Node.JavaDoc.Author != "" { - return gnc.Node.JavaDoc.Author - } - } - return "" - case "comment_see": - if gnc.Node.JavaDoc != nil { - for _, docTag := range gnc.Node.JavaDoc.Tags { - if docTag.TagName == "see" && docTag.Text != "" { - if docTag.Text == val { - return docTag.Text - } - } - } - } - return "" - case "comment_version": - if gnc.Node.JavaDoc != nil { - for _, docTag := range gnc.Node.JavaDoc.Tags { - if docTag.TagName == "version" && docTag.Text != "" { - if docTag.Text == val { - return docTag.Text - } - } - } - } - return "" - case "comment_since": - if gnc.Node.JavaDoc != nil { - for _, docTag := range gnc.Node.JavaDoc.Tags { - if docTag.TagName == "since" && docTag.Text != "" { - if docTag.Text == val { - return docTag.Text - } - } - } - } - return "" - case "comment_param": - if gnc.Node.JavaDoc != nil { - for _, docTag := range gnc.Node.JavaDoc.Tags { - if docTag.TagName == "param" && docTag.Text != "" { - if docTag.Text == val { - return docTag.Text - } - } - } - } - return "" - case "comment_throws": - if gnc.Node.JavaDoc != nil { - for _, docTag := range gnc.Node.JavaDoc.Tags { - if docTag.TagName == "throws" && docTag.Text != "" { - if docTag.Text == val { - return docTag.Text - } - } - } - } - return "" - default: - fmt.Printf("Unsupported attribute key: %s\n", key) - return "" - } -} - -func QueryEntities(graph *CodeGraph, query *queryparser.Query) []*GraphNode { - result := make([]*GraphNode, 0) - - for _, node := range graph.Nodes { - if node.Type == query.Entity { - ctx := GraphNodeContext{Node: node} // Create a context for each node - if query.Conditions.Evaluate(&ctx) { // Use the context in evaluation - result = append(result, node) - } - } - } - return result -} diff --git a/test-src/android/app/src/main/AndroidManifest.xml b/test-src/android/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..def7a2f --- /dev/null +++ b/test-src/android/app/src/main/AndroidManifest.xml @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/test-src/android/app/src/main/java/com/ivb/udacity/adapter/movieGeneralAdapter.java b/test-src/android/app/src/main/java/com/ivb/udacity/adapter/movieGeneralAdapter.java new file mode 100644 index 0000000..0cbbaad --- /dev/null +++ b/test-src/android/app/src/main/java/com/ivb/udacity/adapter/movieGeneralAdapter.java @@ -0,0 +1,86 @@ +package com.ivb.udacity.adapter; + +import android.content.Context; +import android.content.Intent; +import android.support.v4.app.FragmentManager; +import android.support.v7.widget.RecyclerView; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +import com.ivb.udacity.R; +import com.ivb.udacity.modal.movieGeneralModal; +import com.ivb.udacity.movieDetailActivity; +import com.ivb.udacity.movieDetailFragment; +import com.squareup.picasso.Picasso; + +import java.util.List; + +/** + * Created by S.Shivasurya on 1/1/2016 - androidStudio. + */ +public class movieGeneralAdapter extends RecyclerView.Adapter { + private List mMovieGeneralModal; + private Context context; + private boolean mTwoPane; + private FragmentManager fm; + + public movieGeneralAdapter(Context context, List itemList, boolean mTwoPane, FragmentManager fm) { + this.mMovieGeneralModal = itemList; + this.context = context; + this.mTwoPane = mTwoPane; + this.fm = fm; + } + + @Override + public movieGeneralHolder onCreateViewHolder(ViewGroup parent, int viewType) { + View layoutView = LayoutInflater.from(parent.getContext()).inflate(R.layout.movie_cards, null); + movieGeneralHolder rcv = new movieGeneralHolder(layoutView); + return rcv; + } + + @Override + public void onBindViewHolder(movieGeneralHolder holder, final int position) { + holder.movieName.setText(mMovieGeneralModal.get(position).getTitle()); + holder.movieAvg.setText(mMovieGeneralModal.get(position).getmVote()); + //picasso loading here + Picasso.with(context) + .load(mMovieGeneralModal.get(position).getThumbnail()) + .into(holder.moviePhoto); + if (position == 0 && mTwoPane) { + movieDetailFragment fragment = new movieDetailFragment(); + fragment.setMovieData(mMovieGeneralModal.get(0)); + fragment.setArgument(fm); + fm + .beginTransaction() + .replace(R.id.movie_detail_container, fragment) + .commit(); + } + holder.mView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (mTwoPane) { + movieDetailFragment fragment = new movieDetailFragment(); + fragment.setMovieData(mMovieGeneralModal.get(position)); + fragment.setArgument(fm); + fm + .beginTransaction() + .replace(R.id.movie_detail_container, fragment) + .commit(); + } else { + Context context = v.getContext(); + Intent intent = new Intent(context, movieDetailActivity.class); + intent.putExtra("DATA_MOVIE", mMovieGeneralModal.get(position)); + context.startActivity(intent); + } + } + }); + } + + @Override + public int getItemCount() { + return this.mMovieGeneralModal.size(); + } +} + + diff --git a/test-src/android/app/src/main/java/com/ivb/udacity/adapter/movieGeneralHolder.java b/test-src/android/app/src/main/java/com/ivb/udacity/adapter/movieGeneralHolder.java new file mode 100644 index 0000000..b2b2f32 --- /dev/null +++ b/test-src/android/app/src/main/java/com/ivb/udacity/adapter/movieGeneralHolder.java @@ -0,0 +1,34 @@ +package com.ivb.udacity.adapter; + +import android.support.v7.widget.RecyclerView; +import android.view.View; +import android.widget.ImageView; +import android.widget.TextView; +import android.widget.Toast; + +import com.ivb.udacity.R; + +/** + * Created by S.Shivasurya on 1/1/2016 - androidStudio. + */ +public class movieGeneralHolder extends RecyclerView.ViewHolder implements View.OnClickListener { + + public TextView movieName, movieAvg; + public ImageView moviePhoto; + public View mView; + + public movieGeneralHolder(View itemView) { + super(itemView); + itemView.setOnClickListener(this); + mView = itemView; + movieName = (TextView) itemView.findViewById(R.id.movieName); + movieAvg = (TextView) itemView.findViewById(R.id.vote); + moviePhoto = (ImageView) itemView.findViewById(R.id.moviePhoto); + } + + @Override + public void onClick(View view) { + Toast.makeText(view.getContext(), "Clicked Country Position = " + getPosition(), Toast.LENGTH_SHORT).show(); + } +} + diff --git a/test-src/android/app/src/main/java/com/ivb/udacity/constants/constant.java b/test-src/android/app/src/main/java/com/ivb/udacity/constants/constant.java new file mode 100644 index 0000000..d01356b --- /dev/null +++ b/test-src/android/app/src/main/java/com/ivb/udacity/constants/constant.java @@ -0,0 +1,8 @@ +package com.ivb.udacity.constants; + +/** + * Created by S.Shivasurya on 1/10/2016 - androidStudio. + */ +public class constant { + public final static String ACCESS_TOKEN = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"; +} diff --git a/test-src/android/app/src/main/java/com/ivb/udacity/database/favouritesSqliteHelper.java b/test-src/android/app/src/main/java/com/ivb/udacity/database/favouritesSqliteHelper.java new file mode 100644 index 0000000..cf804e7 --- /dev/null +++ b/test-src/android/app/src/main/java/com/ivb/udacity/database/favouritesSqliteHelper.java @@ -0,0 +1,91 @@ +package com.ivb.udacity.database; + +import android.content.ContentValues; +import android.content.Context; +import android.database.Cursor; +import android.database.sqlite.SQLiteDatabase; +import android.database.sqlite.SQLiteOpenHelper; + +import com.ivb.udacity.modal.movieGeneralModal; + +import java.util.ArrayList; +import java.util.List; + +/** + * Created by S.Shivasurya on 1/11/2016 - androidStudio. + */ +public class favouritesSqliteHelper extends SQLiteOpenHelper { + public static final String KEY_ROWID = "id"; + public static final String KEY_THUMBNAIL = "mThumbnail"; + public static final String KEY_MVOTE = "mVote"; + public static final String KEY_TITLE = "mTitle"; + public static final String KEY_PEOPLE = "mPeople"; + public static final String KEY_RELEASEDATE = "mReleaseDate"; + public static final String KEY_OVERVIEW = "mOverview"; + public static final String KEY_REVIEW = "mReview"; + public static final String SQLITE_TABLE = "movies"; + private static final String LOG_TAG = "moviesDB"; + private static final String DATABASE_CREATE = + "CREATE TABLE if not exists " + SQLITE_TABLE + " (" + + KEY_ROWID + " integer PRIMARY KEY," + + KEY_THUMBNAIL + "," + + KEY_TITLE + "," + + KEY_PEOPLE + "," + + KEY_MVOTE + "," + + KEY_OVERVIEW + "," + + KEY_REVIEW + "," + + KEY_RELEASEDATE + "" + + " );"; + + public favouritesSqliteHelper(Context context) { + super(context, LOG_TAG, null, 1); + } + + + @Override + public void onCreate(SQLiteDatabase db) { + db.execSQL(DATABASE_CREATE); + } + + @Override + public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { + db.execSQL("DROP TABLE IF EXISTS " + SQLITE_TABLE); + onCreate(db); + } + + public boolean insertMovie(movieGeneralModal movieGeneralModals) { + SQLiteDatabase db = this.getWritableDatabase(); + ContentValues values = new ContentValues(); + values.put(KEY_ROWID, Integer.parseInt(movieGeneralModals.getmId())); + values.put(KEY_THUMBNAIL, movieGeneralModals.getThumbnail()); + values.put(KEY_TITLE, movieGeneralModals.getTitle()); + values.put(KEY_PEOPLE, movieGeneralModals.getmPeople()); + values.put(KEY_MVOTE, movieGeneralModals.getmVote()); + values.put(KEY_OVERVIEW, movieGeneralModals.getmOverview()); + values.put(KEY_RELEASEDATE, movieGeneralModals.getmReleaseDate()); + values.put(KEY_REVIEW, movieGeneralModals.getmReview()); + + boolean createSuccessful = db.insert(SQLITE_TABLE, null, values) > 0; + db.close(); + return createSuccessful; + } + + public List getAllMovies() { + List movieList = new ArrayList<>(); + String selectQuery = "SELECT * FROM " + SQLITE_TABLE; + + SQLiteDatabase db = this.getReadableDatabase(); + Cursor cursor = db.rawQuery(selectQuery, null); + + if (cursor.moveToFirst()) { + do { + movieGeneralModal movie = new movieGeneralModal(cursor.getString(2), cursor.getString(1), cursor.getString(4), cursor.getString(0), cursor.getString(3), cursor.getString(7), cursor.getString(5)); + movieList.add(movie); + } while (cursor.moveToNext()); + } + cursor.close(); + + return movieList; + } + +} diff --git a/test-src/android/app/src/main/java/com/ivb/udacity/modal/Results.java b/test-src/android/app/src/main/java/com/ivb/udacity/modal/Results.java new file mode 100644 index 0000000..979760d --- /dev/null +++ b/test-src/android/app/src/main/java/com/ivb/udacity/modal/Results.java @@ -0,0 +1,153 @@ +package com.ivb.udacity.modal; + +import java.io.Serializable; + +/** + * Created by S.Shivasurya on 1/1/2016 - androidStudio. + */ +public class Results implements Serializable { + private String vote_average; + + private String backdrop_path; + + private String adult; + + private String id; + + private String title; + + private String overview; + + private String original_language; + + private String[] genre_ids; + + private String release_date; + + private String original_title; + + private String vote_count; + + private String poster_path; + + private String video; + + private String popularity; + + public String getVote_average() { + return vote_average; + } + + public void setVote_average(String vote_average) { + this.vote_average = vote_average; + } + + public String getBackdrop_path() { + return backdrop_path; + } + + public void setBackdrop_path(String backdrop_path) { + this.backdrop_path = backdrop_path; + } + + public String getAdult() { + return adult; + } + + public void setAdult(String adult) { + this.adult = adult; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public String getOverview() { + return overview; + } + + public void setOverview(String overview) { + this.overview = overview; + } + + public String getOriginal_language() { + return original_language; + } + + public void setOriginal_language(String original_language) { + this.original_language = original_language; + } + + public String[] getGenre_ids() { + return genre_ids; + } + + public void setGenre_ids(String[] genre_ids) { + this.genre_ids = genre_ids; + } + + public String getRelease_date() { + return release_date; + } + + public void setRelease_date(String release_date) { + this.release_date = release_date; + } + + public String getOriginal_title() { + return original_title; + } + + public void setOriginal_title(String original_title) { + this.original_title = original_title; + } + + public String getVote_count() { + return vote_count; + } + + public void setVote_count(String vote_count) { + this.vote_count = vote_count; + } + + public String getPoster_path() { + return poster_path; + } + + public void setPoster_path(String poster_path) { + this.poster_path = poster_path; + } + + public String getVideo() { + return video; + } + + public void setVideo(String video) { + this.video = video; + } + + public String getPopularity() { + return popularity; + } + + public void setPopularity(String popularity) { + this.popularity = popularity; + } + + @Override + public String toString() { + return "ClassPojo [vote_average = " + vote_average + ", backdrop_path = " + backdrop_path + ", adult = " + adult + ", id = " + id + ", title = " + title + ", overview = " + overview + ", original_language = " + original_language + ", genre_ids = " + genre_ids + ", release_date = " + release_date + ", original_title = " + original_title + ", vote_count = " + vote_count + ", poster_path = " + poster_path + ", video = " + video + ", popularity = " + popularity + "]"; + } +} diff --git a/test-src/android/app/src/main/java/com/ivb/udacity/modal/movieGeneral.java b/test-src/android/app/src/main/java/com/ivb/udacity/modal/movieGeneral.java new file mode 100644 index 0000000..2cf2bc6 --- /dev/null +++ b/test-src/android/app/src/main/java/com/ivb/udacity/modal/movieGeneral.java @@ -0,0 +1,53 @@ +package com.ivb.udacity.modal; + +import java.io.Serializable; + +/** + * Created by S.Shivasurya on 1/1/2016 - androidStudio. + */ +public class movieGeneral implements Serializable { + private Results[] results; + + private String page; + + private String total_pages; + + private String total_results; + + public Results[] getResults() { + return results; + } + + public void setResults(Results[] results) { + this.results = results; + } + + public String getPage() { + return page; + } + + public void setPage(String page) { + this.page = page; + } + + public String getTotal_pages() { + return total_pages; + } + + public void setTotal_pages(String total_pages) { + this.total_pages = total_pages; + } + + public String getTotal_results() { + return total_results; + } + + public void setTotal_results(String total_results) { + this.total_results = total_results; + } + + @Override + public String toString() { + return "ClassPojo [results = " + results + ", page = " + page + ", total_pages = " + total_pages + ", total_results = " + total_results + "]"; + } +} diff --git a/test-src/android/app/src/main/java/com/ivb/udacity/modal/movieGeneralModal.java b/test-src/android/app/src/main/java/com/ivb/udacity/modal/movieGeneralModal.java new file mode 100644 index 0000000..f5f9f59 --- /dev/null +++ b/test-src/android/app/src/main/java/com/ivb/udacity/modal/movieGeneralModal.java @@ -0,0 +1,63 @@ +package com.ivb.udacity.modal; + +import java.io.Serializable; + +/** + * Created by S.Shivasurya on 1/1/2016 - androidStudio. + */ +public class movieGeneralModal implements Serializable { + String mTitle; + String mThumbnail; + String mVote; + String mId; + String mPeople; + String mReleaseDate; + String mOverview; + String mReview; + + public movieGeneralModal(String mTitle, String mThumbnail, String mVote, String mId, String mPeople, String mReleaseDate, String mOverview) { + this.mThumbnail = mThumbnail; + this.mTitle = mTitle; + this.mVote = mVote; + this.mId = mId; + this.mPeople = mPeople; + this.mReleaseDate = mReleaseDate; + this.mOverview = mOverview; + } + + public String getmReview() { + return this.mReview; + } + + public void setmReview(String mReview) { + this.mReview = mReview; + } + + public String getmOverview() { + return this.mOverview; + } + + public String getmReleaseDate() { + return this.mReleaseDate; + } + + public String getTitle() { + return this.mTitle; + } + + public String getThumbnail() { + String url = "http://image.tmdb.org/t/p/w185/" + this.mThumbnail; + return url; + } + + public String getmId() { + return this.mId; + } + + public String getmPeople() { + return this.mPeople; + } + public String getmVote() { + return this.mVote; + } +} diff --git a/test-src/android/app/src/main/java/com/ivb/udacity/modal/review/Results.java b/test-src/android/app/src/main/java/com/ivb/udacity/modal/review/Results.java new file mode 100644 index 0000000..c459d90 --- /dev/null +++ b/test-src/android/app/src/main/java/com/ivb/udacity/modal/review/Results.java @@ -0,0 +1,51 @@ +package com.ivb.udacity.modal.review; + +/** + * Created by S.Shivasurya on 1/8/2016 - androidStudio. + */ +public class Results { + private String content; + + private String id; + + private String author; + + private String url; + + public String getContent() { + return content; + } + + public void setContent(String content) { + this.content = content; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getAuthor() { + return author; + } + + public void setAuthor(String author) { + this.author = author; + } + + public String getUrl() { + return url; + } + + public void setUrl(String url) { + this.url = url; + } + + @Override + public String toString() { + return "ClassPojo [content = " + content + ", id = " + id + ", author = " + author + ", url = " + url + "]"; + } +} diff --git a/test-src/android/app/src/main/java/com/ivb/udacity/modal/review/movieReview.java b/test-src/android/app/src/main/java/com/ivb/udacity/modal/review/movieReview.java new file mode 100644 index 0000000..2d825a1 --- /dev/null +++ b/test-src/android/app/src/main/java/com/ivb/udacity/modal/review/movieReview.java @@ -0,0 +1,61 @@ +package com.ivb.udacity.modal.review; + +/** + * Created by S.Shivasurya on 1/8/2016 - androidStudio. + */ +public class movieReview { + private String id; + + private Results[] results; + + private String page; + + private String total_pages; + + private String total_results; + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public Results[] getResults() { + return results; + } + + public void setResults(Results[] results) { + this.results = results; + } + + public String getPage() { + return page; + } + + public void setPage(String page) { + this.page = page; + } + + public String getTotal_pages() { + return total_pages; + } + + public void setTotal_pages(String total_pages) { + this.total_pages = total_pages; + } + + public String getTotal_results() { + return total_results; + } + + public void setTotal_results(String total_results) { + this.total_results = total_results; + } + + @Override + public String toString() { + return "ClassPojo [id = " + id + ", results = " + results + ", page = " + page + ", total_pages = " + total_pages + ", total_results = " + total_results + "]"; + } +} diff --git a/test-src/android/app/src/main/java/com/ivb/udacity/modal/trailer/Results.java b/test-src/android/app/src/main/java/com/ivb/udacity/modal/trailer/Results.java new file mode 100644 index 0000000..7cbe8cf --- /dev/null +++ b/test-src/android/app/src/main/java/com/ivb/udacity/modal/trailer/Results.java @@ -0,0 +1,81 @@ +package com.ivb.udacity.modal.trailer; + +/** + * Created by S.Shivasurya on 1/10/2016 - androidStudio. + */ +public class Results { + private String site; + + private String id; + + private String iso_639_1; + + private String name; + + private String type; + + private String key; + + private String size; + + public String getSite() { + return site; + } + + public void setSite(String site) { + this.site = site; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getIso_639_1() { + return iso_639_1; + } + + public void setIso_639_1(String iso_639_1) { + this.iso_639_1 = iso_639_1; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public String getKey() { + return key; + } + + public void setKey(String key) { + this.key = key; + } + + public String getSize() { + return size; + } + + public void setSize(String size) { + this.size = size; + } + + @Override + public String toString() { + return "ClassPojo [site = " + site + ", id = " + id + ", iso_639_1 = " + iso_639_1 + ", name = " + name + ", type = " + type + ", key = " + key + ", size = " + size + "]"; + } +} diff --git a/test-src/android/app/src/main/java/com/ivb/udacity/modal/trailer/movieYoutubeModal.java b/test-src/android/app/src/main/java/com/ivb/udacity/modal/trailer/movieYoutubeModal.java new file mode 100644 index 0000000..10afebe --- /dev/null +++ b/test-src/android/app/src/main/java/com/ivb/udacity/modal/trailer/movieYoutubeModal.java @@ -0,0 +1,32 @@ +package com.ivb.udacity.modal.trailer; + +/** + * Created by S.Shivasurya on 1/10/2016 - androidStudio. + */ +public class movieYoutubeModal { + + private String id; + + private Results[] results; + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public Results[] getResults() { + return results; + } + + public void setResults(Results[] results) { + this.results = results; + } + + @Override + public String toString() { + return "ClassPojo [id = " + id + ", results = " + results + "]"; + } +} diff --git a/test-src/android/app/src/main/java/com/ivb/udacity/movieDetailActivity.java b/test-src/android/app/src/main/java/com/ivb/udacity/movieDetailActivity.java new file mode 100644 index 0000000..d66686c --- /dev/null +++ b/test-src/android/app/src/main/java/com/ivb/udacity/movieDetailActivity.java @@ -0,0 +1,63 @@ +package com.ivb.udacity; + +import android.content.Intent; +import android.os.Bundle; +import android.support.v7.app.AppCompatActivity; +import android.view.MenuItem; + +import com.ivb.udacity.modal.movieGeneralModal; + +/** + * An activity representing a single movie detail screen. This + * activity is only used narrow width devices. On tablet-size devices, + * item details are presented side-by-side with a list of items + * in a {@link movieListActivity}. + * @author shivasurya + * @author nirooba + * @version 1.0 + * @since 2016-02-25 + * @see movieListActivity + * @see movieDetailFragment + */ +public class movieDetailActivity extends AppCompatActivity { + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_movie_detail); + Intent intent = getIntent(); + + getSupportActionBar().setDisplayHomeAsUpEnabled(true); + getSupportActionBar().setDisplayShowHomeEnabled(true); + + // webview.javascriptEnabled(); + webview.getSettings().setJavaScriptEnabled(false); + + movieGeneralModal moviegeneralModal = (movieGeneralModal) intent.getSerializableExtra("DATA_MOVIE"); + + if (savedInstanceState == null) { + + movieDetailFragment fragment = new movieDetailFragment(); + fragment.setMovieData(moviegeneralModal); + getSupportFragmentManager().beginTransaction() + .add(R.id.movie_detail_container, fragment) + .commit(); + } + } + + + @Override + public void onBackPressed() { + super.onBackPressed(); + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + int id = item.getItemId(); + if (id == android.R.id.home) { + onBackPressed(); + return true; + } + return super.onOptionsItemSelected(item); + } +} \ No newline at end of file diff --git a/test-src/android/app/src/main/java/com/ivb/udacity/movieDetailFragment.java b/test-src/android/app/src/main/java/com/ivb/udacity/movieDetailFragment.java new file mode 100644 index 0000000..6f44496 --- /dev/null +++ b/test-src/android/app/src/main/java/com/ivb/udacity/movieDetailFragment.java @@ -0,0 +1,266 @@ +package com.ivb.udacity; + +import android.content.ActivityNotFoundException; +import android.content.Intent; +import android.net.Uri; +import android.os.Bundle; +import android.support.annotation.Nullable; +import android.support.design.widget.FloatingActionButton; +import android.support.v4.app.Fragment; +import android.support.v4.app.FragmentManager; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.TextView; +import android.widget.Toast; + +import com.ivb.udacity.constants.constant; +import com.ivb.udacity.database.favouritesSqliteHelper; +import com.ivb.udacity.modal.movieGeneralModal; +import com.ivb.udacity.modal.review.Results; +import com.ivb.udacity.modal.review.movieReview; +import com.ivb.udacity.modal.trailer.movieYoutubeModal; +import com.ivb.udacity.network.MovieAPI; +import com.ivb.udacity.network.NetworkAPI; +import com.squareup.picasso.Picasso; + +import retrofit.Callback; +import retrofit.RetrofitError; +import retrofit.client.Response; + +/** + * A fragment representing a single movie detail screen. + * This fragment is either contained in a {@link movieListActivity} + * in two-pane mode (on tablets) or a {@link movieDetailActivity} + * on handsets. + */ +public class movieDetailFragment extends Fragment { + + private FragmentManager fm; + private movieGeneralModal moviegeneralModal; + private TextView reviewText, titleText, voteText, peoplesText, calendarText, plotSynopsis; + private ImageView titleImage; + private LinearLayout youtubeViewHolder; + private TextView shareYoutube; + private String shareYoutubeID; + private FloatingActionButton fab; + + public movieDetailFragment() { + + } + + public void setArgument(FragmentManager fm) { + this.fm = fm; + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setHasOptionsMenu(true); + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + View rootView = inflater.inflate(R.layout.movie_detail, container, false); + if (savedInstanceState != null) { + this.moviegeneralModal = (movieGeneralModal) savedInstanceState.getSerializable("DATA"); + } + updateGeneralUI(rootView); + return rootView; + } + + @Override + public void onSaveInstanceState(Bundle outState) { + super.onSaveInstanceState(outState); + outState.putSerializable("DATA", moviegeneralModal); + } + @Override + public void onActivityCreated(@Nullable Bundle savedInstanceState) { + super.onActivityCreated(savedInstanceState); + } + + public void setMovieData(movieGeneralModal moviegeneralModal) { + this.moviegeneralModal = moviegeneralModal; + } + + private void updateGeneralUI(View v) { + titleText = (TextView) v.findViewById(R.id.titleText); + voteText = (TextView) v.findViewById(R.id.rating); + calendarText = (TextView) v.findViewById(R.id.calendar); + peoplesText = (TextView) v.findViewById(R.id.people); + titleImage = (ImageView) v.findViewById(R.id.titleimg); + plotSynopsis = (TextView) v.findViewById(R.id.plotsynopsis); + reviewText = (TextView) v.findViewById(R.id.reviewText); + youtubeViewHolder = (LinearLayout) v.findViewById(R.id.youtubelayout); + shareYoutube = (TextView) v.findViewById(R.id.youtubesharer); + fab = (FloatingActionButton) v.findViewById(R.id.fab); + + titleText.setText(moviegeneralModal.getTitle()); + voteText.setText(moviegeneralModal.getmVote()); + peoplesText.setText(moviegeneralModal.getmPeople()); + calendarText.setText(moviegeneralModal.getmReleaseDate()); + plotSynopsis.setText(moviegeneralModal.getmOverview()); + getMovieReview(reviewText); + Picasso.with(getContext()) + .load(moviegeneralModal.getThumbnail()) + .into(titleImage); + getMovieReview(reviewText); + getTrailer(youtubeViewHolder); + shareYoutube.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (shareYoutubeID != null) { + shareYoutubeIntent(shareYoutubeID); + } else { + Toast.makeText(getContext(), "No Youtube Videos Available! Sorry", Toast.LENGTH_LONG).show(); + } + } + }); + fab.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + saveToDatabase(); + } + }); + } + + protected void saveToDatabase() { + favouritesSqliteHelper db = new favouritesSqliteHelper(getContext()); + if (!reviewText.getText().toString().contains("Sorry")) { + moviegeneralModal.setmReview(reviewText.getText().toString()); + } + boolean b = db.insertMovie(moviegeneralModal); + if (b) + Toast.makeText(getContext(), "Added to Favourites", Toast.LENGTH_LONG).show(); + else + Toast.makeText(getContext(), "Seems Already in Favourites!", Toast.LENGTH_LONG).show(); + } + protected void shareYoutubeIntent(String shareYoutubeID) { + String url = "http://www.youtube.com/watch?v" + shareYoutubeID; + String shareMsg = "hey,there new film named " + moviegeneralModal.getTitle() + " has been released and here is the Trailer link,Have a look at it " + url; + Intent sharingIntent = new Intent(android.content.Intent.ACTION_SEND); + sharingIntent.setType("text/plain"); + sharingIntent.putExtra(android.content.Intent.EXTRA_SUBJECT, "Movies Now - Android App"); + sharingIntent.putExtra(android.content.Intent.EXTRA_TEXT, shareMsg); + startActivity(Intent.createChooser(sharingIntent, getResources().getString(R.string.share_using))); + } + + protected String generateYoutubeThumbnailURL(String id) { + String url = "http://img.youtube.com/vi/" + id + "/mqdefault.jpg"; + return url; + } + + public void watchYoutubeVideo(String id) { + try { + Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse("vnd.youtube:" + id)); + startActivity(intent); + } catch (ActivityNotFoundException ex) { + Intent intent = new Intent(Intent.ACTION_VIEW, + Uri.parse("http://www.youtube.com/watch?v=" + id)); + startActivity(intent); + } + } + + protected void getTrailer(final LinearLayout youtubeViewHolder) { + MovieAPI mMovieAPI = NetworkAPI.createService(MovieAPI.class); + mMovieAPI.fetchVideos(constant.ACCESS_TOKEN, this.moviegeneralModal.getmId(), new Callback() { + + @Override + public void success(movieYoutubeModal movieYoutubeModal, Response response) { + youtubeViewHolder.setPadding(5, 10, 5, 0); + com.ivb.udacity.modal.trailer.Results[] trailer = movieYoutubeModal.getResults(); + if (trailer.length > 0) { + shareYoutubeID = trailer[0].getKey(); + for (final com.ivb.udacity.modal.trailer.Results obj : trailer) { + String url = generateYoutubeThumbnailURL(obj.getKey()); + ImageView myImage = new ImageView(getContext()); + LinearLayout.LayoutParams params = new LinearLayout.LayoutParams( + 180, + LinearLayout.LayoutParams.WRAP_CONTENT + ); + params.leftMargin = 3; + params.rightMargin = 3; + params.topMargin = 6; + params.bottomMargin = 3; + myImage.setLayoutParams(params); + Picasso.with(getContext()) + .load(url) + .into(myImage); + youtubeViewHolder.addView(myImage); + myImage.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + watchYoutubeVideo(obj.getKey()); + } + }); + + } + + } else { + youtubeViewHolder.setPadding(50, 50, 50, 50); + TextView errmsg = new TextView(getContext()); + LinearLayout.LayoutParams params = new LinearLayout.LayoutParams( + LinearLayout.LayoutParams.WRAP_CONTENT, + 30 + ); + errmsg.setLayoutParams(params); + errmsg.setText("That's Bad Luck,No Trailers Found!Check later"); + youtubeViewHolder.addView(errmsg); + } + } + + @Override + public void failure(RetrofitError error) { + youtubeViewHolder.setPadding(50, 50, 50, 50); + TextView errmsg = new TextView(getContext()); + LinearLayout.LayoutParams params = new LinearLayout.LayoutParams( + LinearLayout.LayoutParams.WRAP_CONTENT, + 30 + ); + errmsg.setLayoutParams(params); + errmsg.setText("Network Error! You can't view Trailers Rite Now"); + youtubeViewHolder.addView(errmsg); + + } + }); + } + + protected void getMovieReview(final View review) { + MovieAPI mMovieAPI = NetworkAPI.createService(MovieAPI.class); + mMovieAPI.fetchReview(constant.ACCESS_TOKEN, this.moviegeneralModal.getmId(), new Callback() { + + @Override + public void success(movieReview movieReview, Response response) { + Results[] movieResult = movieReview.getResults(); + if (movieResult.length > 0) + ((TextView) review).setText(movieResult[0].getContent()); + else + ((TextView) review).setText("Sorry No Review is Available Till Now!"); + + } + + @Override + public void failure(RetrofitError error) { + Log.d("error", error.toString()); + ((TextView) review).setText("Sorry! Check Back Latter! Network Error!"); + } + }); + } + + protected void generateThumbnail() { + + } + @Override + public void onDestroy() { + super.onDestroy(); + } + + @Override + public void onPause() { + super.onPause(); + } +} \ No newline at end of file diff --git a/test-src/android/app/src/main/java/com/ivb/udacity/movieListActivity.java b/test-src/android/app/src/main/java/com/ivb/udacity/movieListActivity.java new file mode 100644 index 0000000..fa6f9ad --- /dev/null +++ b/test-src/android/app/src/main/java/com/ivb/udacity/movieListActivity.java @@ -0,0 +1,239 @@ +package com.ivb.udacity; + +import android.content.DialogInterface; +import android.content.res.Configuration; +import android.os.Bundle; +import android.support.annotation.NonNull; +import android.support.v4.app.FragmentManager; +import android.support.v7.app.AlertDialog; +import android.support.v7.app.AppCompatActivity; +import android.support.v7.widget.GridLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.util.DisplayMetrics; +import android.view.Menu; +import android.view.MenuInflater; +import android.view.MenuItem; +import android.view.View; +import android.widget.ImageView; +import android.widget.TextView; +import android.widget.Toast; + +import com.ivb.udacity.adapter.movieGeneralAdapter; +import com.ivb.udacity.constants.constant; +import com.ivb.udacity.database.favouritesSqliteHelper; +import com.ivb.udacity.modal.Results; +import com.ivb.udacity.modal.movieGeneral; +import com.ivb.udacity.modal.movieGeneralModal; +import com.ivb.udacity.network.MovieAPI; +import com.ivb.udacity.network.NetworkAPI; + +import java.util.ArrayList; +import java.util.List; + +import retrofit.Callback; +import retrofit.RetrofitError; +import retrofit.client.Response; + +/** + * An activity representing a list of movies. This activity + * has different presentations for handset and tablet-size devices. On + * handsets, the activity presents a list of items, which when touched, + * lead to a {@link movieDetailActivity} representing + * item details. On tablets, the activity presents the list of items and + * item details side-by-side using two vertical panes. + * @author shivasurya + * @version 1.0 + * @throws ClassCastException + */ + @Deprecated +public class movieListActivity extends AppCompatActivity { + final CharSequence[] items = {" Most Popular ", " Highest Rated ", " My Favourites "}; + private final String MOST_POPULAR = "popularity.desc"; + private final String HIGHLY_RATED = "vote_count.desc"; + View recyclerView; + private AlertDialog choice; + private String FLAG_CURRENT = MOST_POPULAR; + private String FLAG_FAV = "FAVOURITE"; + private TextView errorTextView; + private ImageView errorImageview; + /** + * Whether or not the activity is in two-pane mode, i.e. running on a tablet + * device. + */ + private boolean mTwoPane; + private movieGeneral mMoviegeneralData; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_movie_list); + + + recyclerView = findViewById(R.id.movie_list); + errorImageview = (ImageView) findViewById(R.id.errimg); + errorTextView = (TextView) findViewById(R.id.errtext); + + assert recyclerView != null; + + if (findViewById(R.id.movie_detail_container) != null) { + mTwoPane = true; + } + if (savedInstanceState == null) + FetchMovie((RecyclerView) recyclerView, FLAG_CURRENT); + else { + if (savedInstanceState.getString("CURRENT") == FLAG_FAV) { + FetchMovie((RecyclerView) recyclerView, FLAG_FAV); + } else if (savedInstanceState.getSerializable("adapter") != null) { + mMoviegeneralData = (movieGeneral) savedInstanceState.getSerializable("adapter"); + drawLayout((RecyclerView) recyclerView, mMoviegeneralData); + } else { + FetchMovie((RecyclerView) recyclerView, FLAG_CURRENT); + } + } + + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + MenuInflater inflater = getMenuInflater(); + inflater.inflate(R.menu.main, menu); + return true; + } + + @Deprecated + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case R.id.mapMenu: + showChoices(); + break; + } + return true; + } + + @Deprecated + private void showChoices() { + + choice = new AlertDialog.Builder(this) + .setSingleChoiceItems(items, -1, new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int item) { + switch (item) { + case 0: + FetchMovie((RecyclerView) recyclerView, MOST_POPULAR); + break; + case 1: + FetchMovie((RecyclerView) recyclerView, HIGHLY_RATED); + break; + case 2: + FetchMovie((RecyclerView) recyclerView, FLAG_FAV); + break; + } + choice.dismiss(); + } + }).setTitle("Choose") + .show(); + } + + protected void FetchFavourites(@NonNull final RecyclerView recyclerView) { + favouritesSqliteHelper db = new favouritesSqliteHelper(getApplicationContext()); + List movieGeneralModals = db.getAllMovies(); + if (movieGeneralModals.size() > 0) + attachAdapter(recyclerView, movieGeneralModals); + else { + Toast.makeText(getApplicationContext(), "It seems No Favourites! check back Later", Toast.LENGTH_LONG).show(); + } + } + /** + * Fetch movie data from themoviedb.org + * @param recyclerView + * @param flag + */ + protected void getPaneChanges() throws ClassCastException { + mTwoPane = findViewById(R.id.movie_detail_container) != null; + } + + + @Override + protected void onDestroy() { + super.onDestroy(); + } + + @Override + public void onConfigurationChanged(Configuration newConfig) { + + super.onConfigurationChanged(newConfig); + getPaneChanges(); + } + + @Override + protected void onSaveInstanceState(Bundle outState) { + super.onSaveInstanceState(outState); + outState.putSerializable("adapter", mMoviegeneralData); + outState.putString("CURRENT", FLAG_CURRENT); + + } + + private void attachAdapter(@NonNull final RecyclerView recyclerView, List movieGeneralModals) { + DisplayMetrics displaymetrics = new DisplayMetrics(); + getWindowManager().getDefaultDisplay().getMetrics(displaymetrics); + int width = displaymetrics.widthPixels; + int number; + if (!mTwoPane) { + number = width / 170; + } else { + number = (width / 2) / 170; + } + GridLayoutManager lLayout = new GridLayoutManager(getApplicationContext(), number); + RecyclerView rView = recyclerView; + rView.setHasFixedSize(true); + rView.setLayoutManager(lLayout); + FragmentManager fm = getSupportFragmentManager(); + movieGeneralAdapter mMovieGeneralAdapter = new movieGeneralAdapter(getApplicationContext(), movieGeneralModals, mTwoPane, fm); + rView.setAdapter(mMovieGeneralAdapter); + + } + + private void drawLayout(@NonNull final RecyclerView recyclerView, movieGeneral mMoviegeneral) { + List movieGeneralModals = new ArrayList(); + Results[] mResult = mMoviegeneral.getResults(); + for (Results result : mResult) { + movieGeneralModal obj = new movieGeneralModal(result.getTitle(), result.getPoster_path(), result.getVote_average() + , result.getId(), result.getVote_count(), result.getRelease_date(), result.getOverview()); + movieGeneralModals.add(obj); + } + if (mResult.length > 0) { + attachAdapter(recyclerView, movieGeneralModals); + } else { + errorImageview.setVisibility(View.VISIBLE); + errorTextView.setVisibility(View.VISIBLE); + } + } + + private void FetchMovie(@NonNull final RecyclerView recyclerView, String temp) { + + errorImageview.setVisibility(View.INVISIBLE); + errorTextView.setVisibility(View.INVISIBLE); + errorTextView.setText("Sorry!Network Error! check back Later"); + + FLAG_CURRENT = temp; + if (FLAG_CURRENT != FLAG_FAV) { + MovieAPI mMovieAPI = NetworkAPI.createService(MovieAPI.class); + mMovieAPI.fetchMovies(FLAG_CURRENT, constant.ACCESS_TOKEN, "en", new Callback() { + @Override + public void success(movieGeneral mMoviegeneral, Response response) { + mMoviegeneralData = mMoviegeneral; + drawLayout(recyclerView, mMoviegeneral); + } + + @Override + public void failure(RetrofitError error) { + errorImageview.setVisibility(View.VISIBLE); + errorTextView.setVisibility(View.VISIBLE); + } + }); + } else { + FetchFavourites(recyclerView); + } + } + + +} diff --git a/test-src/android/app/src/main/java/com/ivb/udacity/network/MovieAPI.java b/test-src/android/app/src/main/java/com/ivb/udacity/network/MovieAPI.java new file mode 100644 index 0000000..e990073 --- /dev/null +++ b/test-src/android/app/src/main/java/com/ivb/udacity/network/MovieAPI.java @@ -0,0 +1,40 @@ +package com.ivb.udacity.network; + +import com.ivb.udacity.modal.movieGeneral; +import com.ivb.udacity.modal.review.movieReview; +import com.ivb.udacity.modal.trailer.movieYoutubeModal; + +import retrofit.Callback; +import retrofit.http.GET; +import retrofit.http.Path; +import retrofit.http.Query; + +/** + * Created by S.Shivasurya on 1/1/2016 - androidStudio. + */ +public interface MovieAPI { + + //this method is to fetch the ALL movies with specific sort + @GET("/3/discover/movie") + void fetchMovies( + @Query("sort_by") String mSort, + @Query("api_key") String mApiKey, + @Query("language") String lang, + Callback cb + ); + + @GET("/3/movie/{id}/reviews") + void fetchReview( + @Query("api_key") String mApiKey, + @Path("id") String id, + Callback cb + ); + + @GET("/3/movie/{id}/videos") + void fetchVideos( + @Query("api_key") String mApiKey, + @Path("id") String id, + Callback cb + ); + +} diff --git a/test-src/android/app/src/main/java/com/ivb/udacity/network/NetworkAPI.java b/test-src/android/app/src/main/java/com/ivb/udacity/network/NetworkAPI.java new file mode 100644 index 0000000..2a6cf2a --- /dev/null +++ b/test-src/android/app/src/main/java/com/ivb/udacity/network/NetworkAPI.java @@ -0,0 +1,22 @@ +package com.ivb.udacity.network; + +import com.squareup.okhttp.OkHttpClient; + +import retrofit.RestAdapter; +import retrofit.client.OkClient; + +/** + * Created by S.Shivasurya on 1/1/2016 - androidStudio. + */ +public class NetworkAPI { + public static final String API_BASE_URL = "http://api.themoviedb.org"; + + private static RestAdapter.Builder builder = new RestAdapter.Builder() + .setEndpoint(API_BASE_URL) + .setClient(new OkClient(new OkHttpClient())); + + public static S createService(Class serviceClass) { + RestAdapter adapter = builder.build(); + return adapter.create(serviceClass); + } +} diff --git a/test-src/android/app/src/main/res/drawable/calendar.png b/test-src/android/app/src/main/res/drawable/calendar.png new file mode 100644 index 0000000..0689efa Binary files /dev/null and b/test-src/android/app/src/main/res/drawable/calendar.png differ diff --git a/test-src/android/app/src/main/res/drawable/groups.png b/test-src/android/app/src/main/res/drawable/groups.png new file mode 100644 index 0000000..0ff2a7a Binary files /dev/null and b/test-src/android/app/src/main/res/drawable/groups.png differ diff --git a/test-src/android/app/src/main/res/drawable/ic_action.png b/test-src/android/app/src/main/res/drawable/ic_action.png new file mode 100644 index 0000000..ad1d965 Binary files /dev/null and b/test-src/android/app/src/main/res/drawable/ic_action.png differ diff --git a/test-src/android/app/src/main/res/drawable/ic_launcher.png b/test-src/android/app/src/main/res/drawable/ic_launcher.png new file mode 100644 index 0000000..d1c0044 Binary files /dev/null and b/test-src/android/app/src/main/res/drawable/ic_launcher.png differ diff --git a/test-src/android/app/src/main/res/drawable/menu_main.png b/test-src/android/app/src/main/res/drawable/menu_main.png new file mode 100644 index 0000000..1c292d3 Binary files /dev/null and b/test-src/android/app/src/main/res/drawable/menu_main.png differ diff --git a/test-src/android/app/src/main/res/drawable/mqdefault.jpg b/test-src/android/app/src/main/res/drawable/mqdefault.jpg new file mode 100644 index 0000000..2a47387 Binary files /dev/null and b/test-src/android/app/src/main/res/drawable/mqdefault.jpg differ diff --git a/test-src/android/app/src/main/res/drawable/review.png b/test-src/android/app/src/main/res/drawable/review.png new file mode 100644 index 0000000..610450e Binary files /dev/null and b/test-src/android/app/src/main/res/drawable/review.png differ diff --git a/test-src/android/app/src/main/res/layout-w900dp/movie_list.xml b/test-src/android/app/src/main/res/layout-w900dp/movie_list.xml new file mode 100644 index 0000000..e75247a --- /dev/null +++ b/test-src/android/app/src/main/res/layout-w900dp/movie_list.xml @@ -0,0 +1,36 @@ + + + + + + + + + diff --git a/test-src/android/app/src/main/res/layout/activity_movie_detail.xml b/test-src/android/app/src/main/res/layout/activity_movie_detail.xml new file mode 100644 index 0000000..5f2a628 --- /dev/null +++ b/test-src/android/app/src/main/res/layout/activity_movie_detail.xml @@ -0,0 +1,14 @@ + + + + + + + diff --git a/test-src/android/app/src/main/res/layout/activity_movie_list.xml b/test-src/android/app/src/main/res/layout/activity_movie_list.xml new file mode 100644 index 0000000..c61138b --- /dev/null +++ b/test-src/android/app/src/main/res/layout/activity_movie_list.xml @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + + diff --git a/test-src/android/app/src/main/res/layout/movie_cards.xml b/test-src/android/app/src/main/res/layout/movie_cards.xml new file mode 100644 index 0000000..ff82ec9 --- /dev/null +++ b/test-src/android/app/src/main/res/layout/movie_cards.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + diff --git a/test-src/android/app/src/main/res/layout/movie_detail.xml b/test-src/android/app/src/main/res/layout/movie_detail.xml new file mode 100644 index 0000000..f8419a8 --- /dev/null +++ b/test-src/android/app/src/main/res/layout/movie_detail.xml @@ -0,0 +1,252 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test-src/android/app/src/main/res/layout/movie_list.xml b/test-src/android/app/src/main/res/layout/movie_list.xml new file mode 100644 index 0000000..8380bd1 --- /dev/null +++ b/test-src/android/app/src/main/res/layout/movie_list.xml @@ -0,0 +1,10 @@ + + diff --git a/test-src/android/app/src/main/res/menu/detail.xml b/test-src/android/app/src/main/res/menu/detail.xml new file mode 100644 index 0000000..79d72f9 --- /dev/null +++ b/test-src/android/app/src/main/res/menu/detail.xml @@ -0,0 +1,9 @@ + + + + \ No newline at end of file diff --git a/test-src/android/app/src/main/res/menu/main.xml b/test-src/android/app/src/main/res/menu/main.xml new file mode 100644 index 0000000..aadee93 --- /dev/null +++ b/test-src/android/app/src/main/res/menu/main.xml @@ -0,0 +1,9 @@ + + + + \ No newline at end of file diff --git a/test-src/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/test-src/android/app/src/main/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 0000000..c6bcfb3 Binary files /dev/null and b/test-src/android/app/src/main/res/mipmap-hdpi/ic_launcher.png differ diff --git a/test-src/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/test-src/android/app/src/main/res/mipmap-mdpi/ic_launcher.png new file mode 100644 index 0000000..e9be8d2 Binary files /dev/null and b/test-src/android/app/src/main/res/mipmap-mdpi/ic_launcher.png differ diff --git a/test-src/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/test-src/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png new file mode 100644 index 0000000..74688b3 Binary files /dev/null and b/test-src/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ diff --git a/test-src/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/test-src/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 0000000..128a7b3 Binary files /dev/null and b/test-src/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ diff --git a/test-src/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/test-src/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 0000000..5bbbce3 Binary files /dev/null and b/test-src/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/test-src/android/app/src/main/res/values-v21/styles.xml b/test-src/android/app/src/main/res/values-v21/styles.xml new file mode 100644 index 0000000..dbbdd40 --- /dev/null +++ b/test-src/android/app/src/main/res/values-v21/styles.xml @@ -0,0 +1,9 @@ + + + + diff --git a/test-src/android/app/src/main/res/values-w820dp/dimens.xml b/test-src/android/app/src/main/res/values-w820dp/dimens.xml new file mode 100644 index 0000000..63fc816 --- /dev/null +++ b/test-src/android/app/src/main/res/values-w820dp/dimens.xml @@ -0,0 +1,6 @@ + + + 64dp + diff --git a/test-src/android/app/src/main/res/values/colors.xml b/test-src/android/app/src/main/res/values/colors.xml new file mode 100644 index 0000000..acab235 --- /dev/null +++ b/test-src/android/app/src/main/res/values/colors.xml @@ -0,0 +1,18 @@ + + + #FF5722 + #E64A19 + #795548 + #212121 + #212121 + #B6B6B6 + #F44336 + #BA68C8 + #F50057 + #42A5F5 + #26A69A + #00C853 + #455A64 + #fff + #e7e7e7 + diff --git a/test-src/android/app/src/main/res/values/dimens.xml b/test-src/android/app/src/main/res/values/dimens.xml new file mode 100644 index 0000000..5909abf --- /dev/null +++ b/test-src/android/app/src/main/res/values/dimens.xml @@ -0,0 +1,9 @@ + + + 3dp + 3dp + 16dp + 16dp + 200dp + 200dp + diff --git a/test-src/android/app/src/main/res/values/strings.xml b/test-src/android/app/src/main/res/values/strings.xml new file mode 100644 index 0000000..0761510 --- /dev/null +++ b/test-src/android/app/src/main/res/values/strings.xml @@ -0,0 +1,20 @@ + + Movies Now + My NanoDegree Apps + Spotify Streamer + Scores App + Library App + Build It Bigger + XYZ Reader + CAPSTONE:My Own App + sort + MovieDetailActivity + Share using + Movies Now + Movie + Bad Luck!Network Error + Trailer + SHARE + Plot Synopsis + Review + diff --git a/test-src/android/app/src/main/res/values/styles.xml b/test-src/android/app/src/main/res/values/styles.xml new file mode 100644 index 0000000..35e20e4 --- /dev/null +++ b/test-src/android/app/src/main/res/values/styles.xml @@ -0,0 +1,27 @@ + + + + + + + + +