Reorganize GitPlex server projects

This commit is contained in:
robin shine 2017-02-15 18:30:43 +08:00
parent 295436c249
commit b8ca356829
2386 changed files with 5912 additions and 15714 deletions

View File

@ -1,54 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>server-antlr</artifactId>
<parent>
<groupId>com.gitplex</groupId>
<artifactId>server-parent</artifactId>
<version>1.0-EAP-build26</version>
<relativePath>../parent</relativePath>
</parent>
<build>
<plugins>
<plugin>
<groupId>com.gitplex</groupId>
<artifactId>plugin-maven</artifactId>
</plugin>
<plugin>
<artifactId>maven-source-plugin</artifactId>
</plugin>
<plugin>
<artifactId>maven-javadoc-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.antlr</groupId>
<artifactId>antlr4-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>**/Lex*.g4</exclude>
</excludes>
<libDirectory>${basedir}/src/main/java/com/gitplex/commons/antlr</libDirectory>
<listener>false</listener>
<visitor>false</visitor>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<redirectTestOutputToFile>true</redirectTestOutputToFile>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>com.gitplex</groupId>
<artifactId>server-util</artifactId>
<version>1.0-EAP-build26</version>
</dependency>
</dependencies>
<properties>
<moduleClass>com.gitplex.commons.antlr.PluginModule</moduleClass>
</properties>
</project>

View File

@ -1,343 +0,0 @@
/*
* [The "BSD license"]
* Copyright (c) 2012-2015 Terence Parr
* Copyright (c) 2012-2015 Sam Harwell
* Copyright (c) 2015 Gerald Rosenberg
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**
* A grammar for ANTLR v4 implemented using v4 syntax
*
* Modified 2015.06.16 gbr
* -- update for compatibility with Antlr v4.5
*/
lexer grammar ANTLRv4Lexer;
options {
superClass = LexerAdaptor ;
}
import LexBasic; // Standard set of fragments
tokens {
TOKEN_REF,
RULE_REF,
LEXER_CHAR_SET
}
channels {
OFF_CHANNEL // non-default channel for whitespace and comments
}
// ======================================================
// Lexer specification
//
// -------------------------
// Comments
DOC_COMMENT
: DocComment
;
BLOCK_COMMENT
: BlockComment -> channel(OFF_CHANNEL)
;
LINE_COMMENT
: LineComment -> channel(OFF_CHANNEL)
;
// -------------------------
// Integer
//
INT : DecimalNumeral
;
// -------------------------
// Literal string
//
// ANTLR makes no distinction between a single character literal and a
// multi-character string. All literals are single quote delimited and
// may contain unicode escape sequences of the form \uxxxx, where x
// is a valid hexadecimal number (per Unicode standard).
STRING_LITERAL
: SQuoteLiteral
;
UNTERMINATED_STRING_LITERAL
: USQuoteLiteral
;
// -------------------------
// Arguments
//
// Certain argument lists, such as those specifying call parameters
// to a rule invocation, or input parameters to a rule specification
// are contained within square brackets.
BEGIN_ARGUMENT
: LBrack { handleBeginArgument(); }
;
// -------------------------
// Actions
BEGIN_ACTION
: LBrace -> pushMode(Action)
;
// -------------------------
// Keywords
//
// Keywords may not be used as labels for rules or in any other context where
// they would be ambiguous with the keyword vs some other identifier. OPTIONS,
// TOKENS, & CHANNELS blocks are handled idiomatically in dedicated lexical modes.
OPTIONS : 'options' -> pushMode(Options) ;
TOKENS : 'tokens' -> pushMode(Tokens) ;
CHANNELS : 'channels' -> pushMode(Channels) ;
IMPORT : 'import' ;
FRAGMENT : 'fragment' ;
LEXER : 'lexer' ;
PARSER : 'parser' ;
GRAMMAR : 'grammar' ;
PROTECTED : 'protected' ;
PUBLIC : 'public' ;
PRIVATE : 'private' ;
RETURNS : 'returns' ;
LOCALS : 'locals' ;
THROWS : 'throws' ;
CATCH : 'catch' ;
FINALLY : 'finally' ;
MODE : 'mode' ;
// -------------------------
// Punctuation
COLON : Colon ;
COLONCOLON : DColon ;
COMMA : Comma ;
SEMI : Semi ;
LPAREN : LParen ;
RPAREN : RParen ;
LBRACE : LBrace ;
RBRACE : RBrace ;
RARROW : RArrow ;
LT : Lt ;
GT : Gt ;
ASSIGN : Equal ;
QUESTION : Question ;
STAR : Star ;
PLUS_ASSIGN : PlusAssign ;
PLUS : Plus ;
OR : Pipe ;
DOLLAR : Dollar ;
RANGE : Range ;
DOT : Dot ;
AT : At ;
POUND : Pound ;
NOT : Tilde ;
// -------------------------
// Identifiers - allows unicode rule/token names
ID : Id
;
// -------------------------
// Whitespace
WS : ( Hws | Vws )+ -> channel(OFF_CHANNEL) ;
// -------------------------
// Illegal Characters
//
// This is an illegal character trap which is always the last rule in the
// lexer specification. It matches a single character of any value and being
// the last rule in the file will match when no other rule knows what to do
// about the character. It is reported as an error but is not passed on to the
// parser. This means that the parser to deal with the gramamr file anyway
// but we will not try to analyse or code generate from a file with lexical
// errors.
//
// Comment this rule out to allow the error to be propagated to the parser
ERRCHAR
: . -> channel(HIDDEN)
;
// ======================================================
// Lexer modes
// -------------------------
// Arguments
mode Argument; // E.g., [int x, List<String> a[]]
NESTED_ARGUMENT : LBrack -> type(ARGUMENT_CONTENT), pushMode(Argument) ;
ARGUMENT_ESCAPE : EscAny -> type(ARGUMENT_CONTENT) ;
ARGUMENT_STRING_LITERAL : DQuoteLiteral -> type(ARGUMENT_CONTENT) ;
ARGUMENT_CHAR_LITERAL : SQuoteLiteral -> type(ARGUMENT_CONTENT) ;
END_ARGUMENT : RBrack { handleEndArgument(); } ;
// added this to return non-EOF token type here. EOF does something weird
UNTERMINATED_ARGUMENT : EOF -> popMode ;
ARGUMENT_CONTENT : . ;
// -------------------------
// Actions
//
// Many language targets use {} as block delimiters and so we
// must recursively match {} delimited blocks to balance the
// braces. Additionally, we must make some assumptions about
// literal string representation in the target language. We assume
// that they are delimited by ' or " and so consume these
// in their own alts so as not to inadvertantly match {}.
mode Action;
NESTED_ACTION : LBrace -> type(ACTION_CONTENT), pushMode(Action) ;
ACTION_ESCAPE : EscAny -> type(ACTION_CONTENT) ;
ACTION_STRING_LITERAL : DQuoteLiteral -> type(ACTION_CONTENT) ;
ACTION_CHAR_LITERAL : SQuoteLiteral -> type(ACTION_CONTENT) ;
ACTION_DOC_COMMENT : DocComment -> type(ACTION_CONTENT) ;
ACTION_BLOCK_COMMENT : BlockComment -> type(ACTION_CONTENT) ;
ACTION_LINE_COMMENT : LineComment -> type(ACTION_CONTENT) ;
END_ACTION : RBrace { handleEndAction(); } ;
UNTERMINATED_ACTION : EOF -> popMode ;
ACTION_CONTENT : . ;
// -------------------------
mode Options;
OPT_DOC_COMMENT : DocComment -> type(DOC_COMMENT), channel(OFF_CHANNEL) ;
OPT_BLOCK_COMMENT : BlockComment -> type(BLOCK_COMMENT), channel(OFF_CHANNEL) ;
OPT_LINE_COMMENT : LineComment -> type(LINE_COMMENT), channel(OFF_CHANNEL) ;
OPT_LBRACE : LBrace -> type(LBRACE) ;
OPT_RBRACE : RBrace -> type(RBRACE), popMode ;
OPT_ID : Id -> type(ID) ;
OPT_DOT : Dot -> type(DOT) ;
OPT_ASSIGN : Equal -> type(ASSIGN) ;
OPT_STRING_LITERAL : SQuoteLiteral -> type(STRING_LITERAL) ;
OPT_INT : Int -> type(INT) ;
OPT_STAR : Star -> type(STAR) ;
OPT_SEMI : Semi -> type(SEMI) ;
OPT_WS : ( Hws | Vws )+ -> type(WS), channel(OFF_CHANNEL) ;
// -------------------------
mode Tokens;
TOK_DOC_COMMENT : DocComment -> type(DOC_COMMENT), channel(OFF_CHANNEL) ;
TOK_BLOCK_COMMENT : BlockComment -> type(BLOCK_COMMENT), channel(OFF_CHANNEL) ;
TOK_LINE_COMMENT : LineComment -> type(LINE_COMMENT), channel(OFF_CHANNEL) ;
TOK_LBRACE : LBrace -> type(LBRACE) ;
TOK_RBRACE : RBrace -> type(RBRACE), popMode ;
TOK_ID : Id -> type(ID) ;
TOK_DOT : Dot -> type(DOT) ;
TOK_COMMA : Comma -> type(COMMA) ;
TOK_WS : ( Hws | Vws )+ -> type(WS), channel(OFF_CHANNEL) ;
// -------------------------
mode Channels; // currently same as Tokens mode; distinguished by keyword
CHN_DOC_COMMENT : DocComment -> type(DOC_COMMENT), channel(OFF_CHANNEL) ;
CHN_BLOCK_COMMENT : BlockComment -> type(BLOCK_COMMENT), channel(OFF_CHANNEL) ;
CHN_LINE_COMMENT : LineComment -> type(LINE_COMMENT), channel(OFF_CHANNEL) ;
CHN_LBRACE : LBrace -> type(LBRACE) ;
CHN_RBRACE : RBrace -> type(RBRACE), popMode ;
CHN_ID : Id -> type(ID) ;
CHN_DOT : Dot -> type(DOT) ;
CHN_COMMA : Comma -> type(COMMA) ;
CHN_WS : ( Hws | Vws )+ -> type(WS), channel(OFF_CHANNEL) ;
// -------------------------
mode LexerCharSet;
LEXER_CHAR_SET_BODY
: ( ~[\]\\]
| EscAny
)+ -> more
;
LEXER_CHAR_SET
: RBrack -> popMode
;
UNTERMINATED_CHAR_SET
: EOF -> popMode
;
// ------------------------------------------------------------------------------
// Grammar specific Keywords, Punctuation, etc.
fragment Id : NameStartChar NameChar* ;

View File

@ -1,423 +0,0 @@
/*
* [The "BSD license"]
* Copyright (c) 2012-2014 Terence Parr
* Copyright (c) 2012-2014 Sam Harwell
* Copyright (c) 2015 Gerald Rosenberg
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/* A grammar for ANTLR v4 written in ANTLR v4.
*
* Modified 2015.06.16 gbr
* -- update for compatibility with Antlr v4.5
* -- add mode for channels
* -- moved members to LexerAdaptor
* -- move fragments to imports
*/
parser grammar ANTLRv4Parser;
options {
tokenVocab = ANTLRv4Lexer ;
}
// The main entry point for parsing a v4 grammar.
grammarSpec
: DOC_COMMENT?
grammarType id SEMI
prequelConstruct*
rules
modeSpec*
EOF
;
grammarType
: ( LEXER GRAMMAR
| PARSER GRAMMAR
| GRAMMAR
)
;
// This is the list of all constructs that can be declared before
// the set of rules that compose the grammar, and is invoked 0..n
// times by the grammarPrequel rule.
prequelConstruct
: optionsSpec
| delegateGrammars
| tokensSpec
| channelsSpec
| action
;
// ------------
// Options - things that affect analysis and/or code generation
optionsSpec
: OPTIONS LBRACE (option SEMI)* RBRACE
;
option
: id ASSIGN optionValue
;
optionValue
: id (DOT id)*
| STRING_LITERAL
| actionBlock // TODO: is this valid?
| INT
;
// ------------
// Delegates
delegateGrammars
: IMPORT delegateGrammar (COMMA delegateGrammar)* SEMI
;
delegateGrammar
: id ASSIGN id
| id
;
// ------------
// Tokens & Channels
tokensSpec
: TOKENS LBRACE idList? RBRACE
;
channelsSpec
: CHANNELS LBRACE idList? RBRACE
;
idList
: id ( COMMA id )* COMMA?
;
// Match stuff like @parser::members {int i;}
action
: AT (actionScopeName COLONCOLON)? id actionBlock
;
// Scope names could collide with keywords; allow them as ids for action scopes
actionScopeName
: id
| LEXER
| PARSER
;
actionBlock
: BEGIN_ACTION ACTION_CONTENT* END_ACTION
;
argActionBlock
: BEGIN_ARGUMENT ARGUMENT_CONTENT* END_ARGUMENT
;
modeSpec
: MODE id SEMI lexerRuleSpec*
;
rules
: ruleSpec*
;
ruleSpec
: parserRuleSpec
| lexerRuleSpec
;
parserRuleSpec
: DOC_COMMENT?
ruleModifiers? RULE_REF argActionBlock? ruleReturns? throwsSpec?
localsSpec?
rulePrequel*
COLON
ruleBlock
SEMI
exceptionGroup
;
exceptionGroup
: exceptionHandler* finallyClause?
;
exceptionHandler
: CATCH argActionBlock actionBlock
;
finallyClause
: FINALLY actionBlock
;
rulePrequel
: optionsSpec
| ruleAction
;
ruleReturns
: RETURNS argActionBlock
;
// --------------
// Exception spec
throwsSpec
: THROWS id (COMMA id)*
;
localsSpec
: LOCALS argActionBlock
;
/** Match stuff like @init {int i;} */
ruleAction
: AT id actionBlock
;
ruleModifiers
: ruleModifier+
;
// An individual access modifier for a rule. The 'fragment' modifier
// is an internal indication for lexer rules that they do not match
// from the input but are like subroutines for other lexer rules to
// reuse for certain lexical patterns. The other modifiers are passed
// to the code generation templates and may be ignored by the template
// if they are of no use in that language.
ruleModifier
: PUBLIC
| PRIVATE
| PROTECTED
| FRAGMENT
;
ruleBlock
: ruleAltList
;
ruleAltList
: labeledAlt (OR labeledAlt)*
;
labeledAlt
: alternative (POUND id)?
;
// --------------------
// Lexer rules
lexerRuleSpec
: DOC_COMMENT? FRAGMENT?
TOKEN_REF COLON lexerRuleBlock SEMI
;
lexerRuleBlock
: lexerAltList
;
lexerAltList
: lexerAlt (OR lexerAlt)*
;
lexerAlt
: lexerElements lexerCommands?
| // explicitly allow empty alts
;
lexerElements
: lexerElement+
;
lexerElement
: labeledLexerElement ebnfSuffix?
| lexerAtom ebnfSuffix?
| lexerBlock ebnfSuffix?
| actionBlock QUESTION? // actions only allowed at end of outer alt actually,
; // but preds can be anywhere
labeledLexerElement
: id (ASSIGN|PLUS_ASSIGN)
( lexerAtom
| block
)
;
lexerBlock
: LPAREN lexerAltList RPAREN
;
// E.g., channel(HIDDEN), skip, more, mode(INSIDE), push(INSIDE), pop
lexerCommands
: RARROW lexerCommand (COMMA lexerCommand)*
;
lexerCommand
: lexerCommandName LPAREN lexerCommandExpr RPAREN
| lexerCommandName
;
lexerCommandName
: id
| MODE
;
lexerCommandExpr
: id
| INT
;
// --------------------
// Rule Alts
altList
: alternative (OR alternative)*
;
alternative
: elementOptions? element+
| // explicitly allow empty alts
;
element
: labeledElement
( ebnfSuffix
|
)
| atom
( ebnfSuffix
|
)
| ebnf
| actionBlock QUESTION? // SEMPRED is actionBlock followed by QUESTION
;
labeledElement
: id ( ASSIGN | PLUS_ASSIGN )
( atom
| block
)
;
// --------------------
// EBNF and blocks
ebnf
: block blockSuffix?
;
blockSuffix
: ebnfSuffix // Standard EBNF
;
ebnfSuffix
: QUESTION QUESTION?
| STAR QUESTION?
| PLUS QUESTION?
;
lexerAtom
: range
| terminal
| RULE_REF
| notSet
| LEXER_CHAR_SET
| DOT elementOptions?
;
atom
: range // Range x..y - only valid in lexers
| terminal
| ruleref
| notSet
| DOT elementOptions?
;
// --------------------
// Inverted element set
notSet
: NOT setElement
| NOT blockSet
;
blockSet
: LPAREN setElement (OR setElement)* RPAREN
;
setElement
: TOKEN_REF elementOptions?
| STRING_LITERAL elementOptions?
| range
| LEXER_CHAR_SET
;
// -------------
// Grammar Block
block
: LPAREN
( optionsSpec? ruleAction* COLON )?
altList
RPAREN
;
// ----------------
// Parser rule ref
ruleref
: RULE_REF argActionBlock? elementOptions?
;
// ---------------
// Character Range
range
: STRING_LITERAL RANGE STRING_LITERAL
;
terminal
: TOKEN_REF elementOptions?
| STRING_LITERAL elementOptions?
;
// Terminals may be adorned with certain options when
// reference in the grammar: TOK<,,,>
elementOptions
: LT elementOption (COMMA elementOption)* GT
;
elementOption
: id // default node option
| id ASSIGN (id | STRING_LITERAL) // option assignment
;
id : RULE_REF
| TOKEN_REF
;

View File

@ -1,28 +0,0 @@
package com.gitplex.commons.antlr;
import org.antlr.v4.runtime.Lexer;
import org.antlr.v4.runtime.Parser;
public class AntlrUtils {
public static String getDefaultGrammarFile(Class<?> lexerClass) {
String lexerName = lexerClass.getName().replace(".", "/");
return lexerName.substring(0, lexerName.length() - "Lexer".length()) + ".g4";
}
public static String getDefaultTokenFile(Class<?> lexerClass) {
return lexerClass.getSimpleName() + ".tokens";
}
@SuppressWarnings("unchecked")
public static Class<? extends Lexer> getLexerClass(Class<? extends Parser> parserClass) {
String parserClassName = parserClass.getName();
String lexerClassName = parserClassName.substring(0, parserClassName.length()-"Parser".length()) + "Lexer";
try {
return (Class<? extends Lexer>) Class.forName(lexerClassName);
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}
}
}

View File

@ -1,285 +0,0 @@
/*
* [The "BSD license"]
* Copyright (c) 2014-2015 Gerald Rosenberg
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**
* A generally reusable set of fragments for import in to Lexer grammars.
*
* Modified 2015.06.16 gbr -
* -- generalized for inclusion into the ANTLRv4 grammar distribution
*
*/
lexer grammar LexBasic;
import LexUnicode; // Formal set of Unicode ranges
// ======================================================
// Lexer fragments
//
// -----------------------------------
// Whitespace & Comments
fragment Ws : Hws | Vws ;
fragment Hws : [ \t] ;
fragment Vws : [\r\n\f] ;
fragment DocComment : '/**' .*? ('*/' | EOF) ;
fragment BlockComment : '/*' .*? ('*/' | EOF) ;
fragment LineComment : '//' ~[\r\n]* ;
fragment LineCommentExt : '//' ~'\n'* ( '\n' Hws* '//' ~'\n'* )* ;
// -----------------------------------
// Escapes
// Any kind of escaped character that we can embed within ANTLR literal strings.
fragment EscSeq
: Esc
( [btnfr"'\\] // The standard escaped character set such as tab, newline, etc.
| UnicodeEsc // A Unicode escape sequence
| . // Invalid escape character
| EOF // Incomplete at EOF
)
;
fragment EscAny
: Esc .
;
fragment UnicodeEsc
: 'u' (HexDigit (HexDigit (HexDigit HexDigit?)?)?)?
;
fragment OctalEscape
: OctalDigit
| OctalDigit OctalDigit
| [0-3] OctalDigit OctalDigit
;
// -----------------------------------
// Numerals
fragment HexNumeral
: '0' [xX] HexDigits
;
fragment OctalNumeral
: '0' '_' OctalDigits
;
fragment DecimalNumeral
: '0'
| [1-9] DecDigit*
;
fragment BinaryNumeral
: '0' [bB] BinaryDigits
;
// -----------------------------------
// Digits
fragment HexDigits : HexDigit+ ;
fragment DecDigits : DecDigit+ ;
fragment OctalDigits : OctalDigit+ ;
fragment BinaryDigits : BinaryDigit+ ;
fragment HexDigit : [0-9a-fA-F] ;
fragment DecDigit : [0-9] ;
fragment OctalDigit : [0-7] ;
fragment BinaryDigit : [01] ;
// -----------------------------------
// Literals
fragment BoolLiteral : True | False ;
fragment CharLiteral : SQuote ( EscSeq | ~['\r\n\\] ) SQuote ;
fragment SQuoteLiteral : SQuote ( EscSeq | ~['\r\n\\] )* SQuote ;
fragment DQuoteLiteral : DQuote ( EscSeq | ~["\r\n\\] )* DQuote ;
fragment USQuoteLiteral : SQuote ( EscSeq | ~['\r\n\\] )* ;
fragment DecimalFloatingPointLiteral
: DecDigits DOT DecDigits? ExponentPart? FloatTypeSuffix?
| DOT DecDigits ExponentPart? FloatTypeSuffix?
| DecDigits ExponentPart FloatTypeSuffix?
| DecDigits FloatTypeSuffix
;
fragment ExponentPart
: [eE] [+-]? DecDigits
;
fragment FloatTypeSuffix
: [fFdD]
;
fragment HexadecimalFloatingPointLiteral
: HexSignificand BinaryExponent FloatTypeSuffix?
;
fragment HexSignificand
: HexNumeral DOT?
| '0' [xX] HexDigits? DOT HexDigits
;
fragment BinaryExponent
: [pP] [+-]? DecDigits
;
// -----------------------------------
// Character ranges
fragment NameChar
: NameStartChar
| '0'..'9'
| Underscore
| '\u00B7'
| '\u0300'..'\u036F'
| '\u203F'..'\u2040'
;
fragment NameStartChar
: 'A'..'Z'
| 'a'..'z'
| '\u00C0'..'\u00D6'
| '\u00D8'..'\u00F6'
| '\u00F8'..'\u02FF'
| '\u0370'..'\u037D'
| '\u037F'..'\u1FFF'
| '\u200C'..'\u200D'
| '\u2070'..'\u218F'
| '\u2C00'..'\u2FEF'
| '\u3001'..'\uD7FF'
| '\uF900'..'\uFDCF'
| '\uFDF0'..'\uFFFD'
; // ignores | ['\u10000-'\uEFFFF] ;
fragment JavaLetter
: [a-zA-Z$_] // "java letters" below 0xFF
| JavaUnicodeChars
;
fragment JavaLetterOrDigit
: [a-zA-Z0-9$_] // "java letters or digits" below 0xFF
| JavaUnicodeChars
;
// covers all characters above 0xFF which are not a surrogate
// and UTF-16 surrogate pairs encodings for U+10000 to U+10FFFF
fragment JavaUnicodeChars
: ~[\u0000-\u00FF\uD800-\uDBFF] {Character.isJavaIdentifierPart(_input.LA(-1))}?
| [\uD800-\uDBFF] [\uDC00-\uDFFF] {Character.isJavaIdentifierPart(Character.toCodePoint((char)_input.LA(-2), (char)_input.LA(-1)))}?
;
// -----------------------------------
// Types
fragment Boolean : 'boolean' ;
fragment Byte : 'byte' ;
fragment Short : 'short' ;
fragment Int : 'int' ;
fragment Long : 'long' ;
fragment Char : 'char' ;
fragment Float : 'float' ;
fragment Double : 'double' ;
fragment True : 'true' ;
fragment False : 'false' ;
// -----------------------------------
// Symbols
fragment Esc : '\\' ;
fragment Colon : ':' ;
fragment DColon : '::' ;
fragment SQuote : '\'' ;
fragment DQuote : '"' ;
fragment BQuote : '`' ;
fragment LParen : '(' ;
fragment RParen : ')' ;
fragment LBrace : '{' ;
fragment RBrace : '}' ;
fragment LBrack : '[' ;
fragment RBrack : ']' ;
fragment RArrow : '->' ;
fragment Lt : '<' ;
fragment Gt : '>' ;
fragment Lte : '<=' ;
fragment Gte : '>=' ;
fragment Equal : '=' ;
fragment NotEqual : '!=' ;
fragment Question : '?' ;
fragment Bang : '!' ;
fragment Star : '*' ;
fragment Slash : '/' ;
fragment Percent : '%' ;
fragment Caret : '^' ;
fragment Plus : '+' ;
fragment Minus : '-' ;
fragment PlusAssign : '+=' ;
fragment MinusAssign : '-=' ;
fragment MulAssign : '*=' ;
fragment DivAssign : '/=' ;
fragment AndAssign : '&=' ;
fragment OrAssign : '|=' ;
fragment XOrAssign : '^=' ;
fragment ModAssign : '%=' ;
fragment LShiftAssign : '<<=' ;
fragment RShiftAssign : '>>=' ;
fragment URShiftAssign : '>>>=';
fragment Underscore : '_' ;
fragment Pipe : '|' ;
fragment Amp : '&' ;
fragment And : '&&' ;
fragment Or : '||' ;
fragment Inc : '++' ;
fragment Dec : '--' ;
fragment LShift : '<<' ;
fragment RShift : '>>' ;
fragment Dollar : '$' ;
fragment Comma : ',' ;
fragment Semi : ';' ;
fragment Dot : '.' ;
fragment Range : '..' ;
fragment Ellipsis : '...' ;
fragment At : '@' ;
fragment Pound : '#' ;
fragment Tilde : '~' ;

View File

@ -1,643 +0,0 @@
/*
* [The "BSD license"]
* Copyright (c) 2014-2015 Gerald Rosenberg
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**
* A generally reusable Unicode character set description for import in to Lexer grammars.
*
* Modified 2015.06.16 gbr -
* -- generalized for inclusion into the ANTLRv4 grammar distribution
*
*/
lexer grammar LexUnicode;
// ======================================================
// Lexer fragments
//
fragment UnicodeLetter
: UnicodeClass_LU
| UnicodeClass_LL
| UnicodeClass_LT
| UnicodeClass_LM
| UnicodeClass_LO
;
fragment UnicodeClass_LU
: '\u0041'..'\u005a'
| '\u00c0'..'\u00de'
| '\u00d8'..'\u00de'
| '\u0100'..'\u0136'
| '\u0139'..'\u0147'
| '\u014a'..'\u0178'
| '\u0179'..'\u017d'
| '\u0181'..'\u0182'
| '\u0184'..'\u0186'
| '\u0187'..'\u0189'
| '\u018a'..'\u018b'
| '\u018e'..'\u0191'
| '\u0193'..'\u0194'
| '\u0196'..'\u0198'
| '\u019c'..'\u019d'
| '\u019f'..'\u01a0'
| '\u01a2'..'\u01a6'
| '\u01a7'..'\u01a9'
| '\u01ac'..'\u01ae'
| '\u01af'..'\u01b1'
| '\u01b2'..'\u01b3'
| '\u01b5'..'\u01b7'
| '\u01b8'..'\u01bc'
| '\u01c4'..'\u01cd'
| '\u01cf'..'\u01db'
| '\u01de'..'\u01ee'
| '\u01f1'..'\u01f4'
| '\u01f6'..'\u01f8'
| '\u01fa'..'\u0232'
| '\u023a'..'\u023b'
| '\u023d'..'\u023e'
| '\u0241'..'\u0243'
| '\u0244'..'\u0246'
| '\u0248'..'\u024e'
| '\u0370'..'\u0372'
| '\u0376'..'\u037f'
| '\u0386'..'\u0388'
| '\u0389'..'\u038a'
| '\u038c'..'\u038e'
| '\u038f'..'\u0391'
| '\u0392'..'\u03a1'
| '\u03a3'..'\u03ab'
| '\u03cf'..'\u03d2'
| '\u03d3'..'\u03d4'
| '\u03d8'..'\u03ee'
| '\u03f4'..'\u03f7'
| '\u03f9'..'\u03fa'
| '\u03fd'..'\u042f'
| '\u0460'..'\u0480'
| '\u048a'..'\u04c0'
| '\u04c1'..'\u04cd'
| '\u04d0'..'\u052e'
| '\u0531'..'\u0556'
| '\u10a0'..'\u10c5'
| '\u10c7'..'\u10cd'
| '\u1e00'..'\u1e94'
| '\u1e9e'..'\u1efe'
| '\u1f08'..'\u1f0f'
| '\u1f18'..'\u1f1d'
| '\u1f28'..'\u1f2f'
| '\u1f38'..'\u1f3f'
| '\u1f48'..'\u1f4d'
| '\u1f59'..'\u1f5f'
| '\u1f68'..'\u1f6f'
| '\u1fb8'..'\u1fbb'
| '\u1fc8'..'\u1fcb'
| '\u1fd8'..'\u1fdb'
| '\u1fe8'..'\u1fec'
| '\u1ff8'..'\u1ffb'
| '\u2102'..'\u2107'
| '\u210b'..'\u210d'
| '\u2110'..'\u2112'
| '\u2115'..'\u2119'
| '\u211a'..'\u211d'
| '\u2124'..'\u212a'
| '\u212b'..'\u212d'
| '\u2130'..'\u2133'
| '\u213e'..'\u213f'
| '\u2145'..'\u2183'
| '\u2c00'..'\u2c2e'
| '\u2c60'..'\u2c62'
| '\u2c63'..'\u2c64'
| '\u2c67'..'\u2c6d'
| '\u2c6e'..'\u2c70'
| '\u2c72'..'\u2c75'
| '\u2c7e'..'\u2c80'
| '\u2c82'..'\u2ce2'
| '\u2ceb'..'\u2ced'
| '\u2cf2'..'\ua640'
| '\ua642'..'\ua66c'
| '\ua680'..'\ua69a'
| '\ua722'..'\ua72e'
| '\ua732'..'\ua76e'
| '\ua779'..'\ua77d'
| '\ua77e'..'\ua786'
| '\ua78b'..'\ua78d'
| '\ua790'..'\ua792'
| '\ua796'..'\ua7aa'
| '\ua7ab'..'\ua7ad'
| '\ua7b0'..'\ua7b1'
| '\uff21'..'\uff3a'
;
fragment UnicodeClass_LL
: '\u0061'..'\u007A'
| '\u00b5'..'\u00df'
| '\u00e0'..'\u00f6'
| '\u00f8'..'\u00ff'
| '\u0101'..'\u0137'
| '\u0138'..'\u0148'
| '\u0149'..'\u0177'
| '\u017a'..'\u017e'
| '\u017f'..'\u0180'
| '\u0183'..'\u0185'
| '\u0188'..'\u018c'
| '\u018d'..'\u0192'
| '\u0195'..'\u0199'
| '\u019a'..'\u019b'
| '\u019e'..'\u01a1'
| '\u01a3'..'\u01a5'
| '\u01a8'..'\u01aa'
| '\u01ab'..'\u01ad'
| '\u01b0'..'\u01b4'
| '\u01b6'..'\u01b9'
| '\u01ba'..'\u01bd'
| '\u01be'..'\u01bf'
| '\u01c6'..'\u01cc'
| '\u01ce'..'\u01dc'
| '\u01dd'..'\u01ef'
| '\u01f0'..'\u01f3'
| '\u01f5'..'\u01f9'
| '\u01fb'..'\u0233'
| '\u0234'..'\u0239'
| '\u023c'..'\u023f'
| '\u0240'..'\u0242'
| '\u0247'..'\u024f'
| '\u0250'..'\u0293'
| '\u0295'..'\u02af'
| '\u0371'..'\u0373'
| '\u0377'..'\u037b'
| '\u037c'..'\u037d'
| '\u0390'..'\u03ac'
| '\u03ad'..'\u03ce'
| '\u03d0'..'\u03d1'
| '\u03d5'..'\u03d7'
| '\u03d9'..'\u03ef'
| '\u03f0'..'\u03f3'
| '\u03f5'..'\u03fb'
| '\u03fc'..'\u0430'
| '\u0431'..'\u045f'
| '\u0461'..'\u0481'
| '\u048b'..'\u04bf'
| '\u04c2'..'\u04ce'
| '\u04cf'..'\u052f'
| '\u0561'..'\u0587'
| '\u1d00'..'\u1d2b'
| '\u1d6b'..'\u1d77'
| '\u1d79'..'\u1d9a'
| '\u1e01'..'\u1e95'
| '\u1e96'..'\u1e9d'
| '\u1e9f'..'\u1eff'
| '\u1f00'..'\u1f07'
| '\u1f10'..'\u1f15'
| '\u1f20'..'\u1f27'
| '\u1f30'..'\u1f37'
| '\u1f40'..'\u1f45'
| '\u1f50'..'\u1f57'
| '\u1f60'..'\u1f67'
| '\u1f70'..'\u1f7d'
| '\u1f80'..'\u1f87'
| '\u1f90'..'\u1f97'
| '\u1fa0'..'\u1fa7'
| '\u1fb0'..'\u1fb4'
| '\u1fb6'..'\u1fb7'
| '\u1fbe'..'\u1fc2'
| '\u1fc3'..'\u1fc4'
| '\u1fc6'..'\u1fc7'
| '\u1fd0'..'\u1fd3'
| '\u1fd6'..'\u1fd7'
| '\u1fe0'..'\u1fe7'
| '\u1ff2'..'\u1ff4'
| '\u1ff6'..'\u1ff7'
| '\u210a'..'\u210e'
| '\u210f'..'\u2113'
| '\u212f'..'\u2139'
| '\u213c'..'\u213d'
| '\u2146'..'\u2149'
| '\u214e'..'\u2184'
| '\u2c30'..'\u2c5e'
| '\u2c61'..'\u2c65'
| '\u2c66'..'\u2c6c'
| '\u2c71'..'\u2c73'
| '\u2c74'..'\u2c76'
| '\u2c77'..'\u2c7b'
| '\u2c81'..'\u2ce3'
| '\u2ce4'..'\u2cec'
| '\u2cee'..'\u2cf3'
| '\u2d00'..'\u2d25'
| '\u2d27'..'\u2d2d'
| '\ua641'..'\ua66d'
| '\ua681'..'\ua69b'
| '\ua723'..'\ua72f'
| '\ua730'..'\ua731'
| '\ua733'..'\ua771'
| '\ua772'..'\ua778'
| '\ua77a'..'\ua77c'
| '\ua77f'..'\ua787'
| '\ua78c'..'\ua78e'
| '\ua791'..'\ua793'
| '\ua794'..'\ua795'
| '\ua797'..'\ua7a9'
| '\ua7fa'..'\uab30'
| '\uab31'..'\uab5a'
| '\uab64'..'\uab65'
| '\ufb00'..'\ufb06'
| '\ufb13'..'\ufb17'
| '\uff41'..'\uff5a'
;
fragment UnicodeClass_LT
: '\u01c5'..'\u01cb'
| '\u01f2'..'\u1f88'
| '\u1f89'..'\u1f8f'
| '\u1f98'..'\u1f9f'
| '\u1fa8'..'\u1faf'
| '\u1fbc'..'\u1fcc'
| '\u1ffc'..'\u1ffc'
;
fragment UnicodeClass_LM
: '\u02b0'..'\u02c1'
| '\u02c6'..'\u02d1'
| '\u02e0'..'\u02e4'
| '\u02ec'..'\u02ee'
| '\u0374'..'\u037a'
| '\u0559'..'\u0640'
| '\u06e5'..'\u06e6'
| '\u07f4'..'\u07f5'
| '\u07fa'..'\u081a'
| '\u0824'..'\u0828'
| '\u0971'..'\u0e46'
| '\u0ec6'..'\u10fc'
| '\u17d7'..'\u1843'
| '\u1aa7'..'\u1c78'
| '\u1c79'..'\u1c7d'
| '\u1d2c'..'\u1d6a'
| '\u1d78'..'\u1d9b'
| '\u1d9c'..'\u1dbf'
| '\u2071'..'\u207f'
| '\u2090'..'\u209c'
| '\u2c7c'..'\u2c7d'
| '\u2d6f'..'\u2e2f'
| '\u3005'..'\u3031'
| '\u3032'..'\u3035'
| '\u303b'..'\u309d'
| '\u309e'..'\u30fc'
| '\u30fd'..'\u30fe'
| '\ua015'..'\ua4f8'
| '\ua4f9'..'\ua4fd'
| '\ua60c'..'\ua67f'
| '\ua69c'..'\ua69d'
| '\ua717'..'\ua71f'
| '\ua770'..'\ua788'
| '\ua7f8'..'\ua7f9'
| '\ua9cf'..'\ua9e6'
| '\uaa70'..'\uaadd'
| '\uaaf3'..'\uaaf4'
| '\uab5c'..'\uab5f'
| '\uff70'..'\uff9e'
| '\uff9f'..'\uff9f'
;
fragment UnicodeClass_LO
: '\u00aa'..'\u00ba'
| '\u01bb'..'\u01c0'
| '\u01c1'..'\u01c3'
| '\u0294'..'\u05d0'
| '\u05d1'..'\u05ea'
| '\u05f0'..'\u05f2'
| '\u0620'..'\u063f'
| '\u0641'..'\u064a'
| '\u066e'..'\u066f'
| '\u0671'..'\u06d3'
| '\u06d5'..'\u06ee'
| '\u06ef'..'\u06fa'
| '\u06fb'..'\u06fc'
| '\u06ff'..'\u0710'
| '\u0712'..'\u072f'
| '\u074d'..'\u07a5'
| '\u07b1'..'\u07ca'
| '\u07cb'..'\u07ea'
| '\u0800'..'\u0815'
| '\u0840'..'\u0858'
| '\u08a0'..'\u08b2'
| '\u0904'..'\u0939'
| '\u093d'..'\u0950'
| '\u0958'..'\u0961'
| '\u0972'..'\u0980'
| '\u0985'..'\u098c'
| '\u098f'..'\u0990'
| '\u0993'..'\u09a8'
| '\u09aa'..'\u09b0'
| '\u09b2'..'\u09b6'
| '\u09b7'..'\u09b9'
| '\u09bd'..'\u09ce'
| '\u09dc'..'\u09dd'
| '\u09df'..'\u09e1'
| '\u09f0'..'\u09f1'
| '\u0a05'..'\u0a0a'
| '\u0a0f'..'\u0a10'
| '\u0a13'..'\u0a28'
| '\u0a2a'..'\u0a30'
| '\u0a32'..'\u0a33'
| '\u0a35'..'\u0a36'
| '\u0a38'..'\u0a39'
| '\u0a59'..'\u0a5c'
| '\u0a5e'..'\u0a72'
| '\u0a73'..'\u0a74'
| '\u0a85'..'\u0a8d'
| '\u0a8f'..'\u0a91'
| '\u0a93'..'\u0aa8'
| '\u0aaa'..'\u0ab0'
| '\u0ab2'..'\u0ab3'
| '\u0ab5'..'\u0ab9'
| '\u0abd'..'\u0ad0'
| '\u0ae0'..'\u0ae1'
| '\u0b05'..'\u0b0c'
| '\u0b0f'..'\u0b10'
| '\u0b13'..'\u0b28'
| '\u0b2a'..'\u0b30'
| '\u0b32'..'\u0b33'
| '\u0b35'..'\u0b39'
| '\u0b3d'..'\u0b5c'
| '\u0b5d'..'\u0b5f'
| '\u0b60'..'\u0b61'
| '\u0b71'..'\u0b83'
| '\u0b85'..'\u0b8a'
| '\u0b8e'..'\u0b90'
| '\u0b92'..'\u0b95'
| '\u0b99'..'\u0b9a'
| '\u0b9c'..'\u0b9e'
| '\u0b9f'..'\u0ba3'
| '\u0ba4'..'\u0ba8'
| '\u0ba9'..'\u0baa'
| '\u0bae'..'\u0bb9'
| '\u0bd0'..'\u0c05'
| '\u0c06'..'\u0c0c'
| '\u0c0e'..'\u0c10'
| '\u0c12'..'\u0c28'
| '\u0c2a'..'\u0c39'
| '\u0c3d'..'\u0c58'
| '\u0c59'..'\u0c60'
| '\u0c61'..'\u0c85'
| '\u0c86'..'\u0c8c'
| '\u0c8e'..'\u0c90'
| '\u0c92'..'\u0ca8'
| '\u0caa'..'\u0cb3'
| '\u0cb5'..'\u0cb9'
| '\u0cbd'..'\u0cde'
| '\u0ce0'..'\u0ce1'
| '\u0cf1'..'\u0cf2'
| '\u0d05'..'\u0d0c'
| '\u0d0e'..'\u0d10'
| '\u0d12'..'\u0d3a'
| '\u0d3d'..'\u0d4e'
| '\u0d60'..'\u0d61'
| '\u0d7a'..'\u0d7f'
| '\u0d85'..'\u0d96'
| '\u0d9a'..'\u0db1'
| '\u0db3'..'\u0dbb'
| '\u0dbd'..'\u0dc0'
| '\u0dc1'..'\u0dc6'
| '\u0e01'..'\u0e30'
| '\u0e32'..'\u0e33'
| '\u0e40'..'\u0e45'
| '\u0e81'..'\u0e82'
| '\u0e84'..'\u0e87'
| '\u0e88'..'\u0e8a'
| '\u0e8d'..'\u0e94'
| '\u0e95'..'\u0e97'
| '\u0e99'..'\u0e9f'
| '\u0ea1'..'\u0ea3'
| '\u0ea5'..'\u0ea7'
| '\u0eaa'..'\u0eab'
| '\u0ead'..'\u0eb0'
| '\u0eb2'..'\u0eb3'
| '\u0ebd'..'\u0ec0'
| '\u0ec1'..'\u0ec4'
| '\u0edc'..'\u0edf'
| '\u0f00'..'\u0f40'
| '\u0f41'..'\u0f47'
| '\u0f49'..'\u0f6c'
| '\u0f88'..'\u0f8c'
| '\u1000'..'\u102a'
| '\u103f'..'\u1050'
| '\u1051'..'\u1055'
| '\u105a'..'\u105d'
| '\u1061'..'\u1065'
| '\u1066'..'\u106e'
| '\u106f'..'\u1070'
| '\u1075'..'\u1081'
| '\u108e'..'\u10d0'
| '\u10d1'..'\u10fa'
| '\u10fd'..'\u1248'
| '\u124a'..'\u124d'
| '\u1250'..'\u1256'
| '\u1258'..'\u125a'
| '\u125b'..'\u125d'
| '\u1260'..'\u1288'
| '\u128a'..'\u128d'
| '\u1290'..'\u12b0'
| '\u12b2'..'\u12b5'
| '\u12b8'..'\u12be'
| '\u12c0'..'\u12c2'
| '\u12c3'..'\u12c5'
| '\u12c8'..'\u12d6'
| '\u12d8'..'\u1310'
| '\u1312'..'\u1315'
| '\u1318'..'\u135a'
| '\u1380'..'\u138f'
| '\u13a0'..'\u13f4'
| '\u1401'..'\u166c'
| '\u166f'..'\u167f'
| '\u1681'..'\u169a'
| '\u16a0'..'\u16ea'
| '\u16f1'..'\u16f8'
| '\u1700'..'\u170c'
| '\u170e'..'\u1711'
| '\u1720'..'\u1731'
| '\u1740'..'\u1751'
| '\u1760'..'\u176c'
| '\u176e'..'\u1770'
| '\u1780'..'\u17b3'
| '\u17dc'..'\u1820'
| '\u1821'..'\u1842'
| '\u1844'..'\u1877'
| '\u1880'..'\u18a8'
| '\u18aa'..'\u18b0'
| '\u18b1'..'\u18f5'
| '\u1900'..'\u191e'
| '\u1950'..'\u196d'
| '\u1970'..'\u1974'
| '\u1980'..'\u19ab'
| '\u19c1'..'\u19c7'
| '\u1a00'..'\u1a16'
| '\u1a20'..'\u1a54'
| '\u1b05'..'\u1b33'
| '\u1b45'..'\u1b4b'
| '\u1b83'..'\u1ba0'
| '\u1bae'..'\u1baf'
| '\u1bba'..'\u1be5'
| '\u1c00'..'\u1c23'
| '\u1c4d'..'\u1c4f'
| '\u1c5a'..'\u1c77'
| '\u1ce9'..'\u1cec'
| '\u1cee'..'\u1cf1'
| '\u1cf5'..'\u1cf6'
| '\u2135'..'\u2138'
| '\u2d30'..'\u2d67'
| '\u2d80'..'\u2d96'
| '\u2da0'..'\u2da6'
| '\u2da8'..'\u2dae'
| '\u2db0'..'\u2db6'
| '\u2db8'..'\u2dbe'
| '\u2dc0'..'\u2dc6'
| '\u2dc8'..'\u2dce'
| '\u2dd0'..'\u2dd6'
| '\u2dd8'..'\u2dde'
| '\u3006'..'\u303c'
| '\u3041'..'\u3096'
| '\u309f'..'\u30a1'
| '\u30a2'..'\u30fa'
| '\u30ff'..'\u3105'
| '\u3106'..'\u312d'
| '\u3131'..'\u318e'
| '\u31a0'..'\u31ba'
| '\u31f0'..'\u31ff'
| '\u3400'..'\u4db5'
| '\u4e00'..'\u9fcc'
| '\ua000'..'\ua014'
| '\ua016'..'\ua48c'
| '\ua4d0'..'\ua4f7'
| '\ua500'..'\ua60b'
| '\ua610'..'\ua61f'
| '\ua62a'..'\ua62b'
| '\ua66e'..'\ua6a0'
| '\ua6a1'..'\ua6e5'
| '\ua7f7'..'\ua7fb'
| '\ua7fc'..'\ua801'
| '\ua803'..'\ua805'
| '\ua807'..'\ua80a'
| '\ua80c'..'\ua822'
| '\ua840'..'\ua873'
| '\ua882'..'\ua8b3'
| '\ua8f2'..'\ua8f7'
| '\ua8fb'..'\ua90a'
| '\ua90b'..'\ua925'
| '\ua930'..'\ua946'
| '\ua960'..'\ua97c'
| '\ua984'..'\ua9b2'
| '\ua9e0'..'\ua9e4'
| '\ua9e7'..'\ua9ef'
| '\ua9fa'..'\ua9fe'
| '\uaa00'..'\uaa28'
| '\uaa40'..'\uaa42'
| '\uaa44'..'\uaa4b'
| '\uaa60'..'\uaa6f'
| '\uaa71'..'\uaa76'
| '\uaa7a'..'\uaa7e'
| '\uaa7f'..'\uaaaf'
| '\uaab1'..'\uaab5'
| '\uaab6'..'\uaab9'
| '\uaaba'..'\uaabd'
| '\uaac0'..'\uaac2'
| '\uaadb'..'\uaadc'
| '\uaae0'..'\uaaea'
| '\uaaf2'..'\uab01'
| '\uab02'..'\uab06'
| '\uab09'..'\uab0e'
| '\uab11'..'\uab16'
| '\uab20'..'\uab26'
| '\uab28'..'\uab2e'
| '\uabc0'..'\uabe2'
| '\uac00'..'\ud7a3'
| '\ud7b0'..'\ud7c6'
| '\ud7cb'..'\ud7fb'
| '\uf900'..'\ufa6d'
| '\ufa70'..'\ufad9'
| '\ufb1d'..'\ufb1f'
| '\ufb20'..'\ufb28'
| '\ufb2a'..'\ufb36'
| '\ufb38'..'\ufb3c'
| '\ufb3e'..'\ufb40'
| '\ufb41'..'\ufb43'
| '\ufb44'..'\ufb46'
| '\ufb47'..'\ufbb1'
| '\ufbd3'..'\ufd3d'
| '\ufd50'..'\ufd8f'
| '\ufd92'..'\ufdc7'
| '\ufdf0'..'\ufdfb'
| '\ufe70'..'\ufe74'
| '\ufe76'..'\ufefc'
| '\uff66'..'\uff6f'
| '\uff71'..'\uff9d'
| '\uffa0'..'\uffbe'
| '\uffc2'..'\uffc7'
| '\uffca'..'\uffcf'
| '\uffd2'..'\uffd7'
| '\uffda'..'\uffdc'
;
fragment UnicodeDigit // UnicodeClass_ND
: '\u0030'..'\u0039'
| '\u0660'..'\u0669'
| '\u06f0'..'\u06f9'
| '\u07c0'..'\u07c9'
| '\u0966'..'\u096f'
| '\u09e6'..'\u09ef'
| '\u0a66'..'\u0a6f'
| '\u0ae6'..'\u0aef'
| '\u0b66'..'\u0b6f'
| '\u0be6'..'\u0bef'
| '\u0c66'..'\u0c6f'
| '\u0ce6'..'\u0cef'
| '\u0d66'..'\u0d6f'
| '\u0de6'..'\u0def'
| '\u0e50'..'\u0e59'
| '\u0ed0'..'\u0ed9'
| '\u0f20'..'\u0f29'
| '\u1040'..'\u1049'
| '\u1090'..'\u1099'
| '\u17e0'..'\u17e9'
| '\u1810'..'\u1819'
| '\u1946'..'\u194f'
| '\u19d0'..'\u19d9'
| '\u1a80'..'\u1a89'
| '\u1a90'..'\u1a99'
| '\u1b50'..'\u1b59'
| '\u1bb0'..'\u1bb9'
| '\u1c40'..'\u1c49'
| '\u1c50'..'\u1c59'
| '\ua620'..'\ua629'
| '\ua8d0'..'\ua8d9'
| '\ua900'..'\ua909'
| '\ua9d0'..'\ua9d9'
| '\ua9f0'..'\ua9f9'
| '\uaa50'..'\uaa59'
| '\uabf0'..'\uabf9'
| '\uff10'..'\uff19'
;

View File

@ -1,89 +0,0 @@
package com.gitplex.commons.antlr;
import org.antlr.v4.runtime.CharStream;
import org.antlr.v4.runtime.Lexer;
import org.antlr.v4.runtime.Token;
import org.antlr.v4.runtime.misc.Interval;
import com.gitplex.commons.antlr.ANTLRv4Lexer;
public abstract class LexerAdaptor extends Lexer {
public LexerAdaptor(CharStream input) {
super(input);
}
/**
* Track whether we are inside of a rule and whether it is lexical parser. _currentRuleType==Token.INVALID_TYPE
* means that we are outside of a rule. At the first sign of a rule name reference and _currentRuleType==invalid, we
* can assume that we are starting a parser rule. Similarly, seeing a token reference when not already in rule means
* starting a token rule. The terminating ';' of a rule, flips this back to invalid type.
*
* This is not perfect logic but works. For example, "grammar T;" means that we start and stop a lexical rule for
* the "T;". Dangerous but works.
*
* The whole point of this state information is to distinguish between [..arg actions..] and [charsets]. Char sets
* can only occur in lexical rules and arg actions cannot occur.
*/
private int _currentRuleType = Token.INVALID_TYPE;
public int getCurrentRuleType() {
return _currentRuleType;
}
public void setCurrentRuleType(int ruleType) {
this._currentRuleType = ruleType;
}
protected void handleBeginArgument() {
if (inLexerRule()) {
pushMode(ANTLRv4Lexer.LexerCharSet);
more();
} else {
pushMode(ANTLRv4Lexer.Argument);
}
}
protected void handleEndArgument() {
popMode();
if (_modeStack.size() > 0) {
setType(ANTLRv4Lexer.ARGUMENT_CONTENT);
}
}
protected void handleEndAction() {
popMode();
if (_modeStack.size() > 0) {
setType(ANTLRv4Lexer.ACTION_CONTENT);
}
}
@Override
public Token emit() {
if (_type == ANTLRv4Lexer.ID) {
String firstChar = _input.getText(Interval.of(_tokenStartCharIndex, _tokenStartCharIndex));
if (Character.isUpperCase(firstChar.charAt(0))) {
_type = ANTLRv4Lexer.TOKEN_REF;
} else {
_type = ANTLRv4Lexer.RULE_REF;
}
if (_currentRuleType == Token.INVALID_TYPE) { // if outside of rule def
_currentRuleType = _type; // set to inside lexer or parser rule
}
} else if (_type == ANTLRv4Lexer.SEMI) { // exit rule def
_currentRuleType = Token.INVALID_TYPE;
}
return super.emit();
}
private boolean inLexerRule() {
return _currentRuleType == ANTLRv4Lexer.TOKEN_REF;
}
@SuppressWarnings("unused")
private boolean inParserRule() { // not used, but added for clarity
return _currentRuleType == ANTLRv4Lexer.RULE_REF;
}
}

View File

@ -1,18 +0,0 @@
package com.gitplex.commons.antlr;
import com.gitplex.calla.loader.AbstractPluginModule;
/**
* NOTE: Do not forget to rename moduleClass property defined in the pom if you've renamed this class.
*
*/
public class PluginModule extends AbstractPluginModule {
@Override
protected void configure() {
super.configure();
// put your guice bindings here
}
}

View File

@ -1,585 +0,0 @@
package com.gitplex.commons.antlr.codeassist;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.annotation.Nullable;
import org.antlr.v4.runtime.Lexer;
import org.antlr.v4.runtime.Token;
import com.gitplex.commons.antlr.grammar.AlternativeSpec;
import com.gitplex.commons.antlr.grammar.ElementSpec;
import com.gitplex.commons.antlr.grammar.Grammar;
import com.gitplex.commons.antlr.grammar.RuleRefElementSpec;
import com.gitplex.commons.antlr.grammar.RuleSpec;
import com.gitplex.commons.antlr.grammar.TokenElementSpec;
import com.gitplex.commons.antlr.parser.Chart;
import com.gitplex.commons.antlr.parser.EarleyParser;
import com.gitplex.commons.antlr.parser.Element;
import com.gitplex.commons.antlr.parser.State;
import com.gitplex.commons.util.StringUtils;
import com.google.common.base.Preconditions;
public abstract class CodeAssist implements Serializable {
private static final long serialVersionUID = 1L;
private final Grammar grammar;
public CodeAssist(Grammar grammar) {
this.grammar = grammar;
}
/**
* Code assist constructor
* @param lexerClass
* lexer class to be used to lex code. Other required information such as
* grammar files and token file will be derived from the lexer class
*/
public CodeAssist(Class<? extends Lexer> lexerClass) {
this(new Grammar(lexerClass));
}
/**
* Code assist constructor.
*
* @param lexerClass
* lexer class to be used to lex code
* @param grammarFiles
* grammar files in class path, relative to class path root
* @param tokenFile
* generated tokens file in class path, relative to class path root
*/
public CodeAssist(Class<? extends Lexer> lexerClass, String grammarFiles[], String tokenFile) {
this(new Grammar(lexerClass, grammarFiles, tokenFile));
}
public List<String> getHints(InputStatus inputStatus, String ruleName) {
RuleSpec rule = Preconditions.checkNotNull(grammar.getRule(ruleName));
List<Token> tokens = grammar.lex(inputStatus.getContentBeforeCaret());
EarleyParser parser = new EarleyParser(rule, tokens);
Set<String> hints = new LinkedHashSet<>();
for (Chart chart: getTerminatingCharts(parser)) {
String matchWith = getMatchWith(chart, inputStatus);
for (List<ParentedElement> expectChain: getExpectChains(chart)) {
for (ParentedElement element: expectChain)
hints.addAll(getHints(element, matchWith));
}
}
return new ArrayList<>(hints);
}
private String appendMandatories(InputStatus inputStatus, ElementCompletion completion) {
String inputContent = inputStatus.getContent();
String content = inputContent.substring(0, completion.getReplaceBegin())
+ completion.getReplaceContent();
if (completion.isComplete() && completion.getReplaceEnd() == inputStatus.getCaret()) {
ParentedElement parentElement = completion.getExpectedElement().getParent();
ElementSpec elementSpec = completion.getExpectedElement().getSpec();
for (String mandatory: getMandatoriesAfter(parentElement, elementSpec)) {
String prevContent = content;
content += mandatory;
if (grammar.getTokenTypeByLiteral(mandatory) != null) {
/*
* if mandatory can be appended without space, the last token
* position should remain unchanged in concatenated content
*/
List<Token> tokens = grammar.lex(content);
if (!tokens.isEmpty()) {
Token lastToken = tokens.get(tokens.size()-1);
if (lastToken.getStartIndex() != content.length() - mandatory.length()
|| lastToken.getStopIndex() != content.length()-1) {
content = prevContent + " " + mandatory;
}
} else {
content = prevContent + " " + mandatory;
}
}
}
}
return content + inputContent.substring(completion.getReplaceEnd());
}
public List<InputCompletion> suggest(InputStatus inputStatus, String ruleName, int count) {
RuleSpec rule = Preconditions.checkNotNull(grammar.getRule(ruleName));
List<InputCompletion> inputCompletions = new ArrayList<>();
Map<String, List<ElementCompletion>> label2completions = new LinkedHashMap<>();
for (ElementCompletion completion: suggest(rule, inputStatus, count)) {
List<ElementCompletion> completionsWithLabel = label2completions.get(completion.getLabel());
if (completionsWithLabel == null) {
completionsWithLabel = new ArrayList<>();
label2completions.put(completion.getLabel(), completionsWithLabel);
}
completionsWithLabel.add(completion);
}
String inputContent = inputStatus.getContent();
for (Map.Entry<String, List<ElementCompletion>> entry: label2completions.entrySet()) {
ElementCompletion completion = entry.getValue().get(0);
String content = appendMandatories(inputStatus, completion);
for (int i=1; i<entry.getValue().size(); i++) {
String eachContent = appendMandatories(inputStatus, entry.getValue().get(i));
if (!eachContent.equals(content)) {
// we have multiple mandatories attached to same label, so they are no longer
// mandatories any more
content = completion.complete(inputStatus).getContent();
break;
}
}
/*
* Adjust caret to move it to next place expecting user input if suggestion is
* complete, that is, we move it after all mandatory tokens after the replacement,
* unless user puts caret explicitly in the middle of replacement via suggestion,
* indicating the replacement has some place holders expecting user input.
*/
int caret = completion.getCaret();
if (completion.isComplete() && caret == -1) {
// caret is not at the middle of replacement, so we need to move it to
// be after mandatory tokens if provided suggestion is complete
caret = content.length() - inputContent.length() + completion.getReplaceEnd();
if (content.equals(completion.complete(inputStatus).getContent())) {
// in case mandatory tokens are not added after replacement,
// we skip existing mandatory tokens in current input
String contentAfterCaret = content.substring(caret);
ParentedElement parentElement = completion.getExpectedElement().getParent();
ElementSpec elementSpec = completion.getExpectedElement().getSpec();
caret += skipMandatories(contentAfterCaret, getMandatoriesAfter(parentElement, elementSpec));
}
} else {
if (caret == -1)
caret = completion.getReplaceContent().length();
caret += completion.getReplaceBegin();
}
String replaceContent = content.substring(completion.getReplaceBegin(),
content.length()-inputContent.length()+completion.getReplaceEnd());
inputCompletions.add(new InputCompletion(completion.getReplaceBegin(),
completion.getReplaceEnd(), replaceContent, caret, completion.getLabel(),
completion.getDescription(), completion.getMatchRange()));
}
/*
* remove duplicate suggestions
*/
Set<String> suggestedContents = new HashSet<>();
boolean hasNonWhitespaceSuggestions = false;
for (Iterator<InputCompletion> it = inputCompletions.iterator(); it.hasNext();) {
InputCompletion completion = it.next();
if (!StringUtils.isWhitespace(completion.getReplaceContent()))
hasNonWhitespaceSuggestions = true;
String content = completion.complete(inputStatus).getContent();
if (suggestedContents.contains(content))
it.remove();
else
suggestedContents.add(content);
}
/*
* Preserve whitespace suggestions if there are no other suggestions as we may need to
* insert a white space for other suggestions to appear
*/
if (hasNonWhitespaceSuggestions) {
for (Iterator<InputCompletion> it = inputCompletions.iterator(); it.hasNext();) {
if (it.next().getReplaceContent().trim().length() == 0)
it.remove();
}
}
if (inputCompletions.size() > count)
return inputCompletions.subList(0, count);
else
return inputCompletions;
}
private ParentedElement getElementExpectingTerminal(ParentedElement parent, Element element) {
parent = new ParentedElement(parent, element);
State state = element.getState();
if (state != null) {
// the last element is always the element assumed completed
element = state.getElements().get(state.getElements().size()-1);
return getElementExpectingTerminal(parent, element);
} else {
return parent;
}
}
private void assumeCompleted(EarleyParser parser, State state, int position, Set<State> statesAssumeCompleted) {
Chart startChart = parser.getCharts().get(state.getOriginPosition());
for (State startState: startChart.getStates()) {
if (!startState.isCompleted()) {
ElementSpec nextElement = startState.getExpectedElementSpec();
if (nextElement instanceof RuleRefElementSpec) {
RuleRefElementSpec ruleRefElement = (RuleRefElementSpec) nextElement;
if (ruleRefElement.getRuleName().equals(state.getRuleSpec().getName())) {
List<Element> elements = new ArrayList<>(startState.getElements());
elements.add(new Element(parser, ruleRefElement, position, state));
State parentState = new State(startState.getOriginPosition(),
startState.getRuleSpec(), startState.getAlternativeSpecIndex(),
startState.getExpectedElementSpecIndex(),
startState.isExpectedElementSpecMatchedOnce(),
elements);
if (statesAssumeCompleted.add(parentState))
assumeCompleted(parser, parentState, position, statesAssumeCompleted);
}
}
}
}
}
private List<List<ParentedElement>> getExpectChains(Chart chart) {
int position = chart.getPosition();
EarleyParser parser = chart.getParser();
List<List<ParentedElement>> expectChains = new ArrayList<>();
for (State stateExpectingTerminal: chart.getStatesExpectingTerminal()) {
List<Element> elements = new ArrayList<>(stateExpectingTerminal.getElements());
elements.add(new Element(parser, stateExpectingTerminal.getExpectedElementSpec(), 0, null));
stateExpectingTerminal = new State(stateExpectingTerminal.getOriginPosition(), stateExpectingTerminal.getRuleSpec(),
stateExpectingTerminal.getAlternativeSpecIndex(), stateExpectingTerminal.getExpectedElementSpecIndex(),
stateExpectingTerminal.isExpectedElementSpecMatchedOnce(), elements);
/*
* Calculate all states assuming completed, this way we can get to the root state to
* construct a partial parse tree to provide suggestion contexts
*/
Set<State> statesAssumeCompleted = new HashSet<>();
if (statesAssumeCompleted.add(stateExpectingTerminal))
assumeCompleted(parser, stateExpectingTerminal, position, statesAssumeCompleted);
for (State stateAssumeCompleted: statesAssumeCompleted) {
if (stateAssumeCompleted.getRuleSpec().getName().equals(parser.getRule().getName())
&& stateAssumeCompleted.getOriginPosition() == 0) {
Element rootElement = new Element(parser, null, position, stateAssumeCompleted);
List<ParentedElement> expectChain = new ArrayList<>();
ParentedElement elementExpectingTerminal = getElementExpectingTerminal(null, rootElement);
expectChain.add(elementExpectingTerminal);
/*
* Find out all parent elements not containing any matched tokens, and we will
* ask if there are suggestions for these parent elements later. For instance,
* if we input "Math.", we can provide suggestion for whole method element like
* "max(a, b)"; otherwise, we can only provide suggestion for method name "max".
*/
ParentedElement expectedElement = elementExpectingTerminal.getParent();
while (expectedElement != null) {
if (expectedElement.getState().getElements().size() == 1) {
expectChain.add(expectedElement);
expectedElement = expectedElement.getParent();
} else {
break;
}
}
expectChains.add(expectChain);
}
}
}
return expectChains;
}
private String getMatchWith(Chart chart, InputStatus inputStatus) {
String matchWith;
Token token = chart.getOriginatingToken();
int endCharIndex;
if (token != null) {
endCharIndex = token.getStopIndex()+1;
} else {
endCharIndex = 0;
}
matchWith = inputStatus.getContent().substring(endCharIndex, inputStatus.getCaret());
for (Token each: chart.getParser().getTokens()) {
if (each.getStartIndex() == endCharIndex) {
// we can not trim leading space as it is not optional
return matchWith;
}
}
return StringUtils.trimStart(matchWith);
}
private List<ElementSuggestion> suggest(Chart chart, InputStatus inputStatus, int count) {
List<ElementSuggestion> suggestions = new ArrayList<>();
String matchWith = getMatchWith(chart, inputStatus);
int numSuggested = 0;
for (List<ParentedElement> expectChain: getExpectChains(chart)) {
// goes through the expect chain to check if there are suggestions for expected element
List<InputSuggestion> inputSuggestions = null;
for (ParentedElement element: expectChain) {
inputSuggestions = suggest(element, matchWith, count - numSuggested);
if (inputSuggestions != null) {
if (!inputSuggestions.isEmpty()) {
suggestions.add(new ElementSuggestion(element, matchWith, inputSuggestions));
numSuggested += inputSuggestions.size();
}
break;
}
}
ParentedElement elementExpectingTerminal = expectChain.get(0);
if (inputSuggestions == null && elementExpectingTerminal.getSpec() instanceof TokenElementSpec) {
// no suggestions, let's see if we can provide some default suggestions
inputSuggestions = new ArrayList<>();
TokenElementSpec spec = (TokenElementSpec) elementExpectingTerminal.getSpec();
for (String leadingLiteral: spec.getPossiblePrefixes()) {
if (leadingLiteral.startsWith(matchWith) && leadingLiteral.length()>matchWith.length()) {
List<Token> tokens = grammar.lex(leadingLiteral);
boolean complete = tokens.size() == 1 && tokens.get(0).getType() == spec.getTokenType();
InputSuggestion suggestion = wrapAsSuggestion(elementExpectingTerminal, leadingLiteral, complete);
if (suggestion != null) {
inputSuggestions.add(suggestion);
if (++numSuggested >= count)
break;
}
}
}
if (!inputSuggestions.isEmpty())
suggestions.add(new ElementSuggestion(elementExpectingTerminal, matchWith, inputSuggestions));
}
if (numSuggested >= count)
break;
}
return suggestions;
}
private List<Chart> getTerminatingCharts(EarleyParser parser) {
List<Chart> terminatingCharts = new ArrayList<>();
/*
* Use the second last chart in order to not considering the last matched token.
* This is useful for below cases:
* 1. when the last token matches either a keyword or part of an identifier.
* For instance, the last token can be keyword 'for', but can also match
* identifier 'forme' if the spec allows.
* 2. assume we have a query rule containing multiple criterias, with each
* criteria composed of key/value pair key:value. value needs to be quoted
* if it contains spaces. In this case, we want to achieve the effect that
* if user input value containing spaces without surrounding quotes, we
* suggest the user to quote the value.
*/
if (parser.getCharts().size() >= 2)
terminatingCharts.add(parser.getCharts().get(parser.getCharts().size()-2));
if (parser.getCharts().size() >= 1)
terminatingCharts.add(parser.getCharts().get(parser.getCharts().size()-1));
return terminatingCharts;
}
private List<ElementCompletion> suggest(RuleSpec spec, InputStatus inputStatus, int count) {
List<ElementCompletion> completions = new ArrayList<>();
List<ElementSuggestion> suggestions = new ArrayList<>();
List<Token> tokens = grammar.lex(inputStatus.getContentBeforeCaret());
EarleyParser parser = new EarleyParser(spec, tokens);
int numSuggested = 0;
for (Chart chart: getTerminatingCharts(parser)) {
List<ElementSuggestion> chartSuggestions = suggest(chart, inputStatus, count-numSuggested);
suggestions.addAll(chartSuggestions);
for (ElementSuggestion each: chartSuggestions)
numSuggested += each.getInputSuggestions().size();
if (numSuggested >= count)
break;
}
String inputContent = inputStatus.getContent();
for (ElementSuggestion suggestion: suggestions) {
int replaceBegin = inputStatus.getCaret() - suggestion.getMatchWith().length();
int replaceEnd = inputStatus.getCaret();
/*
* if input around the caret matches spec of the suggestion, we then replace
* the matched text with suggestion, instead of simply inserting the
* suggested content
*/
ElementSpec elementSpec = suggestion.getExpectedElement().getSpec();
String contentAfterReplaceBegin = inputContent.substring(replaceBegin);
int endOfMatch = getEndOfMatch(elementSpec, contentAfterReplaceBegin) + replaceBegin;
tokens = grammar.lex(contentAfterReplaceBegin);
if (endOfMatch > replaceEnd)
replaceEnd = endOfMatch;
String before = inputContent.substring(0, replaceBegin);
for (InputSuggestion inputSuggestion: suggestion.getInputSuggestions()) {
int position = suggestion.getExpectedElement().getRoot().getPosition();
if (position != 0) {
int lastMatchedTokenIndex = position-1;
Token lastMatchedToken = parser.getTokens().get(lastMatchedTokenIndex);
tokens = grammar.lex(before + inputSuggestion.getContent());
/*
* ignore the suggestion if we can not append the suggested content directly.
* This normally indicates that a space is required before the suggestion,
* and we will show the suggestion when user presses the space to make the
* suggestion list less confusing
*/
if (tokens.size() > lastMatchedTokenIndex) {
Token newToken = tokens.get(lastMatchedTokenIndex);
if (lastMatchedToken.getStartIndex() != newToken.getStartIndex()
|| lastMatchedToken.getStopIndex() != newToken.getStopIndex()) {
continue;
}
} else {
continue;
}
}
completions.add(new ElementCompletion(suggestion.getExpectedElement(), replaceBegin,
// replace only if provided suggestion is a complete representation of the element
inputSuggestion.isComplete()?replaceEnd:inputStatus.getCaret(),
inputSuggestion.getContent(), inputSuggestion.getCaret(),
inputSuggestion.isComplete(), inputSuggestion.getLabel(),
inputSuggestion.getDescription(), inputSuggestion.getMatchRange()));
}
}
return completions;
}
private int skipMandatories(String content, List<String> mandatories) {
String mandatory = StringUtils.join(mandatories, "");
mandatory = StringUtils.deleteWhitespace(mandatory);
if (mandatory.length() != 0 && content.length() != 0) {
int mandatoryIndex = 0;
int contentIndex = 0;
while (true) {
char contentChar = content.charAt(contentIndex);
/*
* space may exist between mandatories in user input, but should
* not exist in ANTLR grammar
*/
if (!Character.isWhitespace(contentChar)) {
if (contentChar != mandatory.charAt(mandatoryIndex))
break;
mandatoryIndex++;
}
contentIndex++;
if (mandatoryIndex == mandatory.length() || contentIndex == content.length())
break;
}
if (mandatoryIndex == mandatory.length())
return contentIndex;
else
return 0;
} else {
return 0;
}
}
/*
* Get mandatory literals after specified element. For instance a method may have
* below rule:
* methodName '(' argList ')'
* The mandatories after element methodName will be '('. When a method name is
* suggested, we should add '(' and moves caret after '(' to avoid unnecessary
* key strokes
*/
private List<String> getMandatoriesAfter(ParentedElement parentElement, ElementSpec elementSpec) {
List<String> literals = new ArrayList<>();
if (parentElement != null && elementSpec != null && !elementSpec.isMultiple()) {
AlternativeSpec alternativeSpec = parentElement.getState().getAlternativeSpec();
int specIndex = alternativeSpec.getElements().indexOf(elementSpec);
if (specIndex == alternativeSpec.getElements().size()-1) {
elementSpec = parentElement.getSpec();
parentElement = parentElement.getParent();
return getMandatoriesAfter(parentElement, elementSpec);
} else {
elementSpec = alternativeSpec.getElements().get(specIndex+1);
if (!elementSpec.isOptional()) {
MandatoryScan scan = elementSpec.scanMandatories();
literals = scan.getMandatories();
if (!scan.isStop())
literals.addAll(getMandatoriesAfter(parentElement, elementSpec));
}
}
}
return literals;
}
public Grammar getGrammar() {
return grammar;
}
/**
* Provide suggestions for expected element matching specified string
*
* @param expectedElement
* the element to expect.
* @param matchWith
* the string the suggestion has to match with
* @param count
* maximum number of suggestions to return
* @return
* a list of suggestions. If you do not have any suggestions and want code assist to
* drill down the element to provide default suggestions, return a <tt>null</tt> value
* instead of an empty list
*/
@Nullable
protected abstract List<InputSuggestion> suggest(ParentedElement expectedElement, String matchWith, int count);
protected List<String> getHints(ParentedElement expectedElement, String matchWith) {
return new ArrayList<>();
}
/**
* Get index of next character after the match.
*
* @param spec
* spec to be matched
* @param content
* content to match against
* @return
* index of next character after the match, or 0 if the rule
* does not match any part of the string
*/
protected int getEndOfMatch(ElementSpec spec, String content) {
int endOfMatch = 0;
List<Token> tokens = grammar.lex(content);
if (!tokens.isEmpty() && tokens.get(0).getStartIndex() == 0) {
endOfMatch = spec.getEndOfMatch(tokens);
if (endOfMatch > 0) // there exist an element match
endOfMatch = tokens.get(endOfMatch-1).getStopIndex()+1; // convert to char index
}
return endOfMatch;
}
/**
* Wrap specified literal of specified terminal element as suggestion.
*
* @param expectedElement
* terminal element expecting to be matched next
* @param suggestedLiteral
* a proposed literal of above terminal element defined in grammar
* @param complete
* whether or not above literal is a complete representation of the
* expected terminal element
* @return
* suggestion of the literal, or <tt>null</tt> to suppress this suggestion
*/
@Nullable
protected InputSuggestion wrapAsSuggestion(ParentedElement expectedElement,
String suggestedLiteral, boolean complete) {
if (StringUtils.isNotBlank(suggestedLiteral))
return new InputSuggestion(suggestedLiteral, -1, complete, null, null);
else
return new InputSuggestion(suggestedLiteral, -1, complete, "space", null);
}
}

View File

@ -1,32 +0,0 @@
package com.gitplex.commons.antlr.codeassist;
import javax.annotation.Nullable;
import com.gitplex.jsymbol.Range;
public class ElementCompletion extends InputCompletion {
private static final long serialVersionUID = 1L;
private final boolean complete;
private final ParentedElement expectedElement;
public ElementCompletion(ParentedElement expectedElement, int replaceBegin,
int replaceEnd, String replaceContent, int caret, boolean complete,
@Nullable String label, @Nullable String description, @Nullable Range highlight) {
super(replaceBegin, replaceEnd, replaceContent, caret, label, description, highlight);
this.complete = complete;
this.expectedElement = expectedElement;
}
public ParentedElement getExpectedElement() {
return expectedElement;
}
public boolean isComplete() {
return complete;
}
}

View File

@ -1,32 +0,0 @@
package com.gitplex.commons.antlr.codeassist;
import java.util.List;
public class ElementSuggestion {
private final ParentedElement expectedElement;
private final String matchWith;
private final List<InputSuggestion> inputSuggestions;
public ElementSuggestion(ParentedElement expectedElement,
String matchWith, List<InputSuggestion> inputSuggestions) {
this.expectedElement = expectedElement;
this.matchWith = matchWith;
this.inputSuggestions = inputSuggestions;
}
public ParentedElement getExpectedElement() {
return expectedElement;
}
public String getMatchWith() {
return matchWith;
}
public List<InputSuggestion> getInputSuggestions() {
return inputSuggestions;
}
}

View File

@ -1,103 +0,0 @@
package com.gitplex.commons.antlr.codeassist;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.Nullable;
import org.antlr.v4.runtime.Token;
import com.gitplex.commons.antlr.grammar.ElementSpec;
import com.gitplex.commons.antlr.grammar.Grammar;
import com.gitplex.jsymbol.Range;
public abstract class FenceAware {
private final Grammar grammar;
private final String open;
private final String close;
public FenceAware(Grammar grammar, String open, String close) {
this.grammar = grammar;
this.open = open;
this.close = close;
}
private boolean matches(ElementSpec spec, String content) {
List<Token> tokens = grammar.lex(content);
if (tokens.isEmpty()) {
return content.length() == 0 && spec.isAllowEmpty();
} else {
int start = tokens.get(0).getStartIndex();
int stop = tokens.get(tokens.size()-1).getStopIndex()+1;
return start == 0 && stop == content.length() && spec.getEndOfMatch(tokens) == tokens.size();
}
}
public List<InputSuggestion> suggest(ElementSpec spec, String matchWith, int count) {
String unfencedMatchWith = matchWith;
if (matchWith.startsWith(open))
unfencedMatchWith = unfencedMatchWith.substring(open.length());
unfencedMatchWith = unfencedMatchWith.trim();
List<InputSuggestion> suggestions = match(unfencedMatchWith, count);
if (suggestions != null) {
List<InputSuggestion> checkedSuggestions = new ArrayList<>();
for (InputSuggestion suggestion: suggestions) {
String content = suggestion.getContent();
int caret = suggestion.getCaret();
if (!matches(spec, content)) {
content = open + content + close;
Range matchRange = suggestion.getMatchRange();
if (caret != -1)
caret += open.length();
if (matchRange != null)
matchRange = new Range(matchRange.getFrom()+open.length(), matchRange.getTo()+open.length());
checkedSuggestions.add(new InputSuggestion(content, caret, true, suggestion.getDescription(), matchRange));
} else {
checkedSuggestions.add(suggestion);
}
}
/*
* Check to see if the matchWith should be surrounded and return as a suggestion if no other
* suggestions. For instance, you may have a rule requiring that value containing spaces
* should be quoted, in this case, below code will suggest you to quote the value if it
* contains spaces as otherwise it will fail the match below
*/
if (checkedSuggestions.isEmpty() && matchWith.length() != 0 && !matches(spec, unfencedMatchWith)) {
unfencedMatchWith = open + unfencedMatchWith + close;
if (matches(spec, unfencedMatchWith)) {
Range matchRange = new Range(1, unfencedMatchWith.length()-1);
checkedSuggestions.add(new InputSuggestion(unfencedMatchWith, getFencingDescription(), matchRange));
}
}
if (checkedSuggestions.isEmpty() && matchWith.length() == 0)
checkedSuggestions.add(new InputSuggestion(open, null, null));
return checkedSuggestions;
} else {
return null;
}
}
protected String getFencingDescription() {
return null;
}
/**
* Match with provided string to give a list of suggestions
*
* @param unfencedMatchWith
* string with fencing literals removed
* @return
* a list of suggestions. If you do not have any suggestions and want code assist to
* drill down the element to provide default suggestions, return a <tt>null</tt> value
* instead of an empty list
*/
@Nullable
protected abstract List<InputSuggestion> match(String unfencedMatchWith, int count);
}

View File

@ -1,80 +0,0 @@
package com.gitplex.commons.antlr.codeassist;
import java.io.Serializable;
import javax.annotation.Nullable;
import com.gitplex.jsymbol.Range;
public class InputCompletion implements Serializable {
private static final long serialVersionUID = 1L;
private final int replaceBegin;
private final int replaceEnd;
private final String replaceContent;
private final int caret;
private final String label;
private final String description;
private final Range matchRange;
public InputCompletion(int replaceBegin, int replaceEnd, String replaceContent,
int caret, @Nullable String label, @Nullable String description, @Nullable Range matchRange) {
this.replaceBegin = replaceBegin;
this.replaceEnd = replaceEnd;
this.replaceContent = replaceContent;
this.caret = caret;
if (label != null)
this.label = label;
else
this.label = replaceContent;
this.description = description;
this.matchRange = matchRange;
}
public InputCompletion(InputCompletion completion) {
this(completion.getReplaceBegin(), completion.getReplaceEnd(), completion.getReplaceContent(),
completion.getCaret(), completion.getLabel(), completion.getDescription(), completion.getMatchRange());
}
public int getReplaceBegin() {
return replaceBegin;
}
public int getReplaceEnd() {
return replaceEnd;
}
public String getReplaceContent() {
return replaceContent;
}
public int getCaret() {
return caret;
}
public String getLabel() {
return label;
}
public String getDescription() {
return description;
}
public Range getMatchRange() {
return matchRange;
}
public InputStatus complete(InputStatus inputStatus) {
String beforeContent = inputStatus.getContent().substring(0, replaceBegin);
String afterContent = inputStatus.getContent().substring(replaceEnd, inputStatus.getContent().length());
return new InputStatus(beforeContent + replaceContent + afterContent, caret);
}
}

View File

@ -1,43 +0,0 @@
package com.gitplex.commons.antlr.codeassist;
import java.io.Serializable;
public class InputStatus implements Serializable {
private static final long serialVersionUID = 1L;
private final String content;
private final int caret;
public InputStatus(String content, int caret) {
this.content = content;
this.caret = caret;
}
public InputStatus(String content) {
this(content, content.length());
}
public String getContent() {
return content;
}
public int getCaret() {
return caret;
}
public String getContentBeforeCaret() {
return content.substring(0, caret);
}
public String getContentAfterCaret() {
return content.substring(caret, content.length());
}
@Override
public String toString() {
return content + ":" + caret;
}
}

View File

@ -1,78 +0,0 @@
package com.gitplex.commons.antlr.codeassist;
import javax.annotation.Nullable;
import com.gitplex.jsymbol.Range;
public class InputSuggestion extends InputStatus {
private static final long serialVersionUID = 1L;
private final boolean complete;
private final String label;
private final String description;
private final Range matchRange;
/**
* Construct the input suggestion.
*
* @param content
* content of the suggestion
* @param caret
* caret of the suggestion
* @param complete
* whether or not the suggested content is a complete representation of
* corresponding element spec
* @param description
* description of the suggestion
* @param matchRange
* optionally specifies range of the string being matched against user input
*/
public InputSuggestion(String content, int caret, boolean complete, @Nullable String label,
@Nullable String description, @Nullable Range matchRange) {
super(content, caret);
this.complete = complete;
this.label = label;
this.description = description;
this.matchRange = matchRange;
}
public InputSuggestion(String content, int caret, boolean complete,
@Nullable String description, @Nullable Range matchRange) {
this(content, caret, complete, null, description, matchRange);
}
public InputSuggestion(String content, @Nullable String description, @Nullable Range highlight) {
this(content, -1, true, description, highlight);
}
public InputSuggestion(String content, @Nullable Range matchRange) {
this(content, null, matchRange);
}
public InputSuggestion(String content) {
this(content, null);
}
public boolean isComplete() {
return complete;
}
public String getLabel() {
return label;
}
@Nullable
public String getDescription() {
return description;
}
@Nullable
public Range getMatchRange() {
return matchRange;
}
}

View File

@ -1,41 +0,0 @@
package com.gitplex.commons.antlr.codeassist;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
public class MandatoryScan implements Serializable {
private static final long serialVersionUID = 1L;
private final List<String> mandatories;
private final boolean stop;
/**
* Construct mandatory scan object
*
* @param mandatories
* list of mandatory literals
* @param stop
* sign to whether or not the mandatory scan should be
* stopped
*/
public MandatoryScan(List<String> mandatories, boolean stop) {
this.mandatories = mandatories;
this.stop = stop;
}
public List<String> getMandatories() {
return mandatories;
}
public boolean isStop() {
return stop;
}
public static MandatoryScan stop() {
return new MandatoryScan(new ArrayList<String>(), true);
}
}

View File

@ -1,63 +0,0 @@
package com.gitplex.commons.antlr.codeassist;
import javax.annotation.Nullable;
import com.gitplex.commons.antlr.parser.Element;
public class ParentedElement extends Element {
private final ParentedElement parent;
public ParentedElement(@Nullable ParentedElement parent, Element element) {
super(element.getParser(), element.getSpec(), element.getPosition(), element.getState());
this.parent = parent;
}
/**
* Get parent element
*
* @return
* parent element, or <tt>null</tt> if current element is root
*/
@Nullable
public ParentedElement getParent() {
return parent;
}
@Nullable
public ParentedElement findParentByLabel(String label) {
ParentedElement current = parent;
while (current != null) {
if (label.equals(current.getLabel()))
return current;
current = current.parent;
}
return null;
}
@Nullable
public ParentedElement findParentByRule(String ruleName) {
ParentedElement current = parent;
while (current != null) {
if (ruleName.equals(current.getState().getRuleSpec().getName()))
return current;
current = current.parent;
}
return null;
}
/**
* Get root element
*
* @return
* root element
*/
public ParentedElement getRoot() {
if (parent == null)
return this;
else
return parent.getRoot();
}
}

View File

@ -1,7 +0,0 @@
package com.gitplex.commons.antlr.codeassist;
import java.util.List;
public interface Suggester {
List<InputSuggestion> suggest(String matchWith);
}

View File

@ -1,13 +0,0 @@
grammar CodeAssistTest1;
selfReference: 'ab' | selfReference 'cd';
mandatories: 'ab' 'c' | 'ab' 'c' | ('cd' ('ef' 'g')) 'h';
notRealAmbiguity: NUMBER+ NUMBER;
NUMBER: [1-9]+;
ID: [a-z]+;
WS: [ \t\r\n]+ -> skip;

View File

@ -1,44 +0,0 @@
grammar CodeAssistTest2;
query: criteria+ EOF;
criteria: revisionCriteria | before | after | committer | author | path | message;
revisionCriteria
: revision # SingleRevision
| EXCLUDE revision # RevisionExclusion
| revision Range revision # RevisionRange
;
revision: (BRANCH|TAG|ID) Value;
before: BEFORE Value;
after: AFTER Value;
committer: COMMITTER Value;
author: AUTHOR Value;
path: PATH Value;
message: MESSAGE Value;
BRANCH: 'branch';
TAG: 'tag';
ID: 'id';
BEFORE: 'before';
AFTER: 'after';
MESSAGE: 'message';
COMMITTER: 'committer';
AUTHOR: 'author';
PATH: 'path';
EXCLUDE: '^';
Range: '..' | '...';
Value: '(' (ESCAPE|~[()\\])+? ')';
fragment
ESCAPE: '\\'[()\\];
WS: [ \t\r\n]+ -> skip;

View File

@ -1,15 +0,0 @@
grammar CodeAssistTest3;
query: criteria+ EOF;
criteria: ('title'|'author') ':' value;
value: QuotedValue|NQuotedValue;
QuotedValue: '"' (ESCAPE|~["\\])+? '"';
NQuotedValue: [a-zA-Z1-9_]+;
fragment
ESCAPE: '\\'["\\];
WS: [ \t\r\n]+ -> skip;

View File

@ -1,7 +0,0 @@
grammar CodeAssistTest4;
stat: expr ';' | ID '=' expr ';' | ';';
expr: INT | ID | expr ('+'|'-'|'*'|'/') expr | '(' expr ')';
ID: [a-zA-Z]+;
INT: [0-9]+;
WS: [ \t\n]+ -> skip;

View File

@ -1,383 +0,0 @@
lexer grammar CodeAssistTest5Lexer;
@ header {
}
SELECT
: 'select'
;
FROM
: 'from'
;
WHERE
: 'where'
;
AND
: 'and' | '&&'
;
OR
: 'or' | '||'
;
XOR
: 'xor'
;
IS
: 'is'
;
NULL
: 'null'
;
LIKE
: 'like'
;
IN
: 'in'
;
EXISTS
: 'exists'
;
ALL
: 'all'
;
ANY
: 'any'
;
TRUE
: 'true'
;
FALSE
: 'false'
;
DIVIDE
: 'div' | '/'
;
MOD
: 'mod' | '%'
;
BETWEEN
: 'between'
;
REGEXP
: 'regexp'
;
PLUS
: '+'
;
MINUS
: '-'
;
NEGATION
: '~'
;
VERTBAR
: '|'
;
BITAND
: '&'
;
POWER_OP
: '^'
;
BINARY
: 'binary'
;
SHIFT_LEFT
: '<<'
;
SHIFT_RIGHT
: '>>'
;
ESCAPE
: 'escape'
;
ASTERISK
: '*'
;
RPAREN
: ')'
;
LPAREN
: '('
;
RBRACK
: ']'
;
LBRACK
: '['
;
COLON
: ':'
;
ALL_FIELDS
: '.*'
;
EQ
: '='
;
LTH
: '<'
;
GTH
: '>'
;
NOT_EQ
: '!='
;
NOT
: 'not'
;
LET
: '<='
;
GET
: '>='
;
SEMI
: ';'
;
COMMA
: ','
;
DOT
: '.'
;
COLLATE
: 'collate'
;
INNER
: 'inner'
;
OUTER
: 'outer'
;
JOIN
: 'join'
;
CROSS
: 'cross'
;
USING
: 'using'
;
INDEX
: 'index'
;
KEY
: 'key'
;
ORDER
: 'order'
;
GROUP
: 'group'
;
BY
: 'by'
;
FOR
: 'for'
;
USE
: 'use'
;
IGNORE
: 'ignore'
;
PARTITION
: 'partition'
;
STRAIGHT_JOIN
: 'straight_join'
;
NATURAL
: 'natural'
;
LEFT
: 'left'
;
RIGHT
: 'right'
;
OJ
: 'oj'
;
ON
: 'on'
;
ID
: ( 'a' .. 'z' | 'A' .. 'Z' | '_' )+
;
INT
: '0' .. '9'+
;
NEWLINE
: '\r'? '\n' -> skip
;
WS
: ( ' ' | '\t' | '\n' | '\r' )+ -> skip
;
USER_VAR
: '@' ( USER_VAR_SUBFIX1 | USER_VAR_SUBFIX2 | USER_VAR_SUBFIX3 | USER_VAR_SUBFIX4 )
;
fragment USER_VAR_SUBFIX1
: ( '`' ( ~ '`' )+ '`' )
;
fragment USER_VAR_SUBFIX2
: ( '\'' ( ~ '\'' )+ '\'' )
;
fragment USER_VAR_SUBFIX3
: ( '\"' ( ~ '\"' )+ '\"' )
;
fragment USER_VAR_SUBFIX4
: ( 'A' .. 'Z' | 'a' .. 'z' | '_' | '$' | '0' .. '9' | DOT )+
;

View File

@ -1,169 +0,0 @@
parser grammar CodeAssistTest5Parser;
options
{ tokenVocab = CodeAssistTest5Lexer; }
stat
: select_clause+
;
schema_name
: ID
;
select_clause
: SELECT column_list_clause ( FROM table_references )? ( where_clause )?
;
table_name
: ID
;
table_alias
: ID
;
column_name
: ( ( schema_name DOT )? tableName=ID DOT )? columnName=ID ( column_name_alias )? | ( table_alias DOT )? ID | USER_VAR ( column_name_alias )?
;
column_name_alias
: ID
;
index_name
: ID
;
column_list
: LPAREN column_name ( COMMA column_name )* RPAREN
;
column_list_clause
: column_name ( COMMA column_name )*
;
from_clause
: FROM table_name ( COMMA table_name )*
;
select_key
: SELECT
;
where_clause
: WHERE expression
;
expression
: simple_expression ( expr_op simple_expression )*
;
element
: USER_VAR | ID | ( '|' ID '|' ) | INT | column_name
;
right_element
: element
;
left_element
: element
;
target_element
: element
;
relational_op
: EQ | LTH | GTH | NOT_EQ | LET | GET
;
expr_op
: AND | XOR | OR | NOT
;
between_op
: BETWEEN
;
is_or_is_not
: IS | IS NOT
;
simple_expression
: left_element relational_op right_element | target_element between_op left_element AND right_element | target_element is_or_is_not NULL
;
table_references
: table_reference ( ( COMMA table_reference ) | join_clause )*
;
table_reference
: table_factor1 | table_atom
;
table_factor1
: table_factor2 ( ( INNER | CROSS )? JOIN table_atom ( join_condition )? )?
;
table_factor2
: table_factor3 ( STRAIGHT_JOIN table_atom ( ON expression )? )?
;
table_factor3
: table_factor4 ( ( LEFT | RIGHT ) ( OUTER )? JOIN table_factor4 join_condition )?
;
table_factor4
: table_atom ( NATURAL ( ( LEFT | RIGHT ) ( OUTER )? )? JOIN table_atom )?
;
table_atom
: ( table_name ( partition_clause )? ( table_alias )? ( index_hint_list )? ) | ( subquery subquery_alias ) | ( LPAREN table_references RPAREN ) | ( OJ table_reference LEFT OUTER JOIN table_reference ON expression )
;
join_clause
: ( ( INNER | CROSS )? JOIN table_atom ( join_condition )? ) | ( STRAIGHT_JOIN table_atom ( ON expression )? ) | ( ( LEFT | RIGHT ) ( OUTER )? JOIN table_factor4 join_condition ) | ( NATURAL ( ( LEFT | RIGHT ) ( OUTER )? )? JOIN table_atom )
;
join_condition
: ( ON expression ( expr_op expression )* ) | ( USING column_list )
;
index_hint_list
: index_hint ( COMMA index_hint )*
;
index_options
: ( INDEX | KEY ) ( FOR ( ( JOIN ) | ( ORDER BY ) | ( GROUP BY ) ) )?
;
index_hint
: USE index_options LPAREN ( index_list )? RPAREN | IGNORE index_options LPAREN index_list RPAREN
;
index_list
: index_name ( COMMA index_name )*
;
partition_clause
: PARTITION LPAREN partition_names RPAREN
;
partition_names
: partition_name ( COMMA partition_name )*
;
partition_name
: ID
;
subquery_alias
: ID
;
subquery
: LPAREN select_clause RPAREN
;

View File

@ -1,38 +0,0 @@
package com.gitplex.commons.antlr.grammar;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.lang3.StringUtils;
public class AlternativeSpec implements Serializable {
private static final long serialVersionUID = 1L;
private final String label;
private final List<ElementSpec> elements;
public AlternativeSpec(String label, List<ElementSpec> elements) {
this.label = label;
this.elements = elements;
}
public String getLabel() {
return label;
}
public List<ElementSpec> getElements() {
return elements;
}
@Override
public String toString() {
List<String> elementStrings = new ArrayList<>();
for (ElementSpec element: elements)
elementStrings.add(element.toString());
return StringUtils.join(elementStrings, " ");
}
}

View File

@ -1,41 +0,0 @@
package com.gitplex.commons.antlr.grammar;
import java.util.Set;
import com.gitplex.commons.antlr.codeassist.MandatoryScan;
import com.google.common.collect.Sets;
public class AnyTokenElementSpec extends TerminalElementSpec {
private static final long serialVersionUID = 1L;
public AnyTokenElementSpec(String label, Multiplicity multiplicity) {
super(label, multiplicity);
}
@Override
public MandatoryScan scanMandatories() {
return MandatoryScan.stop();
}
@Override
protected String toStringOnce() {
return ".";
}
@Override
public boolean isToken(int tokenType) {
return true;
}
@Override
public Set<String> getPossiblePrefixes() {
return Sets.newLinkedHashSet();
}
@Override
protected boolean isAllowEmptyOnce() {
return false;
}
}

View File

@ -1,78 +0,0 @@
package com.gitplex.commons.antlr.grammar;
import java.io.Serializable;
import java.util.List;
import java.util.Set;
import org.antlr.v4.runtime.Token;
import com.gitplex.commons.antlr.codeassist.MandatoryScan;
public abstract class ElementSpec implements Serializable {
private static final long serialVersionUID = 1L;
public enum Multiplicity{ONE, ZERO_OR_ONE, ZERO_OR_MORE, ONE_OR_MORE};
private final String label;
private final Multiplicity multiplicity;
public ElementSpec(String label, Multiplicity multiplicity) {
this.label = label;
this.multiplicity = multiplicity;
}
public String getLabel() {
return label;
}
public Multiplicity getMultiplicity() {
return multiplicity;
}
public boolean isOptional() {
return multiplicity == Multiplicity.ZERO_OR_MORE || multiplicity == Multiplicity.ZERO_OR_ONE;
}
public boolean isMultiple() {
return multiplicity == Multiplicity.ONE_OR_MORE || multiplicity == Multiplicity.ZERO_OR_MORE;
}
public abstract Set<String> getPossiblePrefixes();
protected abstract boolean isAllowEmptyOnce();
public boolean isAllowEmpty() {
if (isOptional())
return true;
else
return isAllowEmptyOnce();
}
public abstract MandatoryScan scanMandatories();
public final String toString() {
if (multiplicity == Multiplicity.ONE)
return toStringOnce();
else if (multiplicity == Multiplicity.ONE_OR_MORE)
return toStringOnce() + "+";
else if (multiplicity == Multiplicity.ZERO_OR_MORE)
return toStringOnce() + "*";
else
return toStringOnce() + "?";
}
/**
* Get the next token index after match of current spec.
*
* @param tokens
* tokens to match against
* @return
* index of next token after the match, or 0 if the spec does not
* match any tokens
*/
public abstract int getEndOfMatch(List<Token> tokens);
protected abstract String toStringOnce();
}

View File

@ -1,422 +0,0 @@
package com.gitplex.commons.antlr.grammar;
import java.io.IOException;
import java.io.InputStream;
import java.io.Serializable;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import javax.annotation.Nullable;
import org.antlr.v4.runtime.ANTLRInputStream;
import org.antlr.v4.runtime.BailErrorStrategy;
import org.antlr.v4.runtime.CharStream;
import org.antlr.v4.runtime.CommonTokenStream;
import org.antlr.v4.runtime.Lexer;
import org.antlr.v4.runtime.Token;
import org.antlr.v4.runtime.tree.TerminalNode;
import org.apache.commons.io.IOUtils;
import com.gitplex.commons.antlr.ANTLRv4Lexer;
import com.gitplex.commons.antlr.ANTLRv4Parser;
import com.gitplex.commons.antlr.AntlrUtils;
import com.gitplex.commons.antlr.ANTLRv4Parser.AlternativeContext;
import com.gitplex.commons.antlr.ANTLRv4Parser.AtomContext;
import com.gitplex.commons.antlr.ANTLRv4Parser.BlockContext;
import com.gitplex.commons.antlr.ANTLRv4Parser.EbnfContext;
import com.gitplex.commons.antlr.ANTLRv4Parser.EbnfSuffixContext;
import com.gitplex.commons.antlr.ANTLRv4Parser.ElementContext;
import com.gitplex.commons.antlr.ANTLRv4Parser.GrammarSpecContext;
import com.gitplex.commons.antlr.ANTLRv4Parser.LabeledAltContext;
import com.gitplex.commons.antlr.ANTLRv4Parser.LabeledElementContext;
import com.gitplex.commons.antlr.ANTLRv4Parser.LabeledLexerElementContext;
import com.gitplex.commons.antlr.ANTLRv4Parser.LexerAltContext;
import com.gitplex.commons.antlr.ANTLRv4Parser.LexerAtomContext;
import com.gitplex.commons.antlr.ANTLRv4Parser.LexerBlockContext;
import com.gitplex.commons.antlr.ANTLRv4Parser.LexerElementContext;
import com.gitplex.commons.antlr.ANTLRv4Parser.LexerRuleBlockContext;
import com.gitplex.commons.antlr.ANTLRv4Parser.LexerRuleSpecContext;
import com.gitplex.commons.antlr.ANTLRv4Parser.ModeSpecContext;
import com.gitplex.commons.antlr.ANTLRv4Parser.NotSetContext;
import com.gitplex.commons.antlr.ANTLRv4Parser.ParserRuleSpecContext;
import com.gitplex.commons.antlr.ANTLRv4Parser.RuleBlockContext;
import com.gitplex.commons.antlr.ANTLRv4Parser.RuleSpecContext;
import com.gitplex.commons.antlr.ANTLRv4Parser.SetElementContext;
import com.gitplex.commons.antlr.grammar.ElementSpec.Multiplicity;
import com.gitplex.commons.util.StringUtils;
public class Grammar implements Serializable {
private static final long serialVersionUID = 1L;
private final Class<? extends Lexer> lexerClass;
private transient Constructor<? extends Lexer> lexerCtor;
private final Map<String, RuleSpec> rules = new HashMap<>();
private final Map<String, Integer> tokenTypesByLiteral = new HashMap<>();
private final Map<String, Integer> tokenTypesByRule = new HashMap<>();
private final Set<String> blockRuleNames = new HashSet<>();
/**
* Code assist constructor
* @param lexerClass
* lexer class to be used to lex code. Other required information such as
* grammar files and token file will be derived from the lexer class
*/
public Grammar(Class<? extends Lexer> lexerClass) {
this(lexerClass, new String[]{AntlrUtils.getDefaultGrammarFile(lexerClass)},
AntlrUtils.getDefaultTokenFile(lexerClass));
}
/**
* Code assist constructor.
*
* @param lexerClass
* lexer class to be used to lex code
* @param grammarFiles
* grammar files in class path, relative to class path root
* @param tokenFile
* generated tokens file in class path, relative to class path root
*/
public Grammar(Class<? extends Lexer> lexerClass, String grammarFiles[], String tokenFile) {
this.lexerClass = lexerClass;
tokenTypesByRule.put("EOF", Token.EOF);
try (InputStream is = getClass().getClassLoader().getResourceAsStream(tokenFile)) {
for (String line: IOUtils.readLines(is)) {
String key = StringUtils.substringBeforeLast(line, "=");
Integer value = Integer.valueOf(StringUtils.substringAfterLast(line, "="));
if (key.startsWith("'"))
tokenTypesByLiteral.put(key.substring(1, key.length()-1), value);
else
tokenTypesByRule.put(key, value);
}
} catch (IOException e) {
throw new RuntimeException(e);
}
for (String grammarFile: grammarFiles) {
try (InputStream is = getClass().getClassLoader().getResourceAsStream(grammarFile)) {
ANTLRv4Lexer lexer = new ANTLRv4Lexer(new ANTLRInputStream(is));
CommonTokenStream tokens = new CommonTokenStream(lexer);
ANTLRv4Parser parser = new ANTLRv4Parser(tokens);
parser.removeErrorListeners();
parser.setErrorHandler(new BailErrorStrategy());
GrammarSpecContext grammarSpecContext = parser.grammarSpec();
for (RuleSpecContext ruleSpecContext: grammarSpecContext.rules().ruleSpec()) {
RuleSpec rule = newRule(ruleSpecContext);
rules.put(rule.getName(), rule);
}
for (ModeSpecContext modeSpecContext: grammarSpecContext.modeSpec()) {
for (LexerRuleSpecContext lexerRuleSpecContext: modeSpecContext.lexerRuleSpec()) {
RuleSpec rule = newRule(lexerRuleSpecContext);
rules.put(rule.getName(), rule);
}
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
// initialize rule properties to avoid changing grammar after
// the constructor
for (RuleSpec rule: rules.values()) {
rule.isAllowEmpty();
rule.getPossiblePrefixes();
rule.scanMandatories();
}
}
private Constructor<? extends Lexer> getLexerCtor() {
if (lexerCtor == null) {
try {
lexerCtor = lexerClass.getConstructor(CharStream.class);
} catch (NoSuchMethodException | SecurityException e) {
throw new RuntimeException(e);
}
}
return lexerCtor;
}
private RuleSpec newRule(RuleSpecContext ruleSpecContext) {
ParserRuleSpecContext parserRuleSpecContext = ruleSpecContext.parserRuleSpec();
if (parserRuleSpecContext != null) {
String name = parserRuleSpecContext.RULE_REF().getText();
List<AlternativeSpec> alternatives = new ArrayList<>();
RuleBlockContext ruleBlockContext = parserRuleSpecContext.ruleBlock();
for (LabeledAltContext labeledAltContext: ruleBlockContext.ruleAltList().labeledAlt())
alternatives.add(newAltenative(labeledAltContext));
return new RuleSpec(name, alternatives);
} else {
return newRule(ruleSpecContext.lexerRuleSpec());
}
}
private RuleSpec newRule(LexerRuleSpecContext lexerRuleSpecContext) {
String name;
List<AlternativeSpec> alternatives = new ArrayList<>();
name = lexerRuleSpecContext.TOKEN_REF().getText();
LexerRuleBlockContext lexerRuleBlockContext = lexerRuleSpecContext.lexerRuleBlock();
for (LexerAltContext lexerAltContext: lexerRuleBlockContext.lexerAltList().lexerAlt())
alternatives.add(newAltenative(lexerAltContext));
return new RuleSpec(name, alternatives);
}
private AlternativeSpec newAltenative(LexerAltContext lexerAltContext) {
List<ElementSpec> elements = new ArrayList<>();
if (lexerAltContext.lexerElements() != null) {
for (LexerElementContext lexerElementContext: lexerAltContext.lexerElements().lexerElement()) {
ElementSpec element = newElement(lexerElementContext);
if (element != null)
elements.add(element);
}
}
return new AlternativeSpec(null, elements);
}
private AlternativeSpec newAltenative(LabeledAltContext labeledAltContext) {
String label;
if (labeledAltContext.id() != null)
label = labeledAltContext.id().getText();
else
label = null;
return newAltenative(label, labeledAltContext.alternative());
}
@Nullable
private ElementSpec newElement(LexerElementContext lexerElementContext) {
LabeledLexerElementContext labeledLexerElementContext = lexerElementContext.labeledLexerElement();
if (labeledLexerElementContext != null) {
String label = labeledLexerElementContext.id().getText();
LexerAtomContext lexerAtomContext = labeledLexerElementContext.lexerAtom();
if (lexerAtomContext != null)
return newElement(label, lexerAtomContext, lexerElementContext.ebnfSuffix());
else
return newElement(label, labeledLexerElementContext.block(), lexerElementContext.ebnfSuffix());
} else if (lexerElementContext.lexerAtom() != null) {
return newElement(null, lexerElementContext.lexerAtom(), lexerElementContext.ebnfSuffix());
} else if (lexerElementContext.lexerBlock() != null) {
return newElement(null, lexerElementContext.lexerBlock(), lexerElementContext.ebnfSuffix());
} else {
return null;
}
}
private AlternativeSpec newAltenative(@Nullable String label, AlternativeContext alternativeContext) {
List<ElementSpec> elements = new ArrayList<>();
for (ElementContext elementContext: alternativeContext.element()) {
ElementSpec element = newElement(elementContext);
if (element != null)
elements.add(element);
}
return new AlternativeSpec(label, elements);
}
@Nullable
private ElementSpec newElement(ElementContext elementContext) {
LabeledElementContext labeledElementContext = elementContext.labeledElement();
if (labeledElementContext != null) {
String label = labeledElementContext.id().getText();
AtomContext atomContext = labeledElementContext.atom();
if (atomContext != null)
return newElement(label, atomContext, elementContext.ebnfSuffix());
else
return newElement(label, labeledElementContext.block(), elementContext.ebnfSuffix());
} else if (elementContext.atom() != null) {
return newElement(null, elementContext.atom(), elementContext.ebnfSuffix());
} else if (elementContext.ebnf() != null) {
return newElement(elementContext.ebnf());
} else {
return null;
}
}
@Nullable
private ElementSpec newElement(String label, AtomContext atomContext, EbnfSuffixContext ebnfSuffixContext) {
Multiplicity multiplicity = newMultiplicity(ebnfSuffixContext);
if (atomContext.terminal() != null) {
if (atomContext.terminal().TOKEN_REF() != null) {
String ruleName = atomContext.terminal().TOKEN_REF().getText();
int tokenType = tokenTypesByRule.get(ruleName);
if (tokenType != Token.EOF)
return new LexerRuleRefElementSpec(this ,label, multiplicity, tokenType, ruleName);
else
return null;
} else {
String literal = getLiteral(atomContext.terminal().STRING_LITERAL());
int tokenType = tokenTypesByLiteral.get(literal);
return new LiteralElementSpec(label, multiplicity, tokenType, literal);
}
} else if (atomContext.ruleref() != null) {
return new RuleRefElementSpec(this, label, multiplicity, atomContext.ruleref().RULE_REF().getText());
} else if (atomContext.notSet() != null) {
return new NotTokenElementSpec(this, label, multiplicity, getNegativeTokenTypes(atomContext.notSet()));
} else if (atomContext.DOT() != null) {
return new AnyTokenElementSpec(label, multiplicity);
} else {
throw new IllegalStateException();
}
}
private String getLiteral(TerminalNode terminal) {
String literal = terminal.getText();
return literal.substring(1, literal.length()-1);
}
@Nullable
private ElementSpec newElement(String label, LexerAtomContext lexerAtomContext, EbnfSuffixContext ebnfSuffixContext) {
Multiplicity multiplicity = newMultiplicity(ebnfSuffixContext);
if (lexerAtomContext.terminal() != null) {
if (lexerAtomContext.terminal().TOKEN_REF() != null) {
String ruleName = lexerAtomContext.terminal().TOKEN_REF().getText();
Integer tokenType = tokenTypesByRule.get(ruleName);
if (tokenType == null) // fragment rule
tokenType = 0;
if (tokenType != Token.EOF)
return new LexerRuleRefElementSpec(this, label, multiplicity, tokenType, ruleName);
else
return null;
} else {
String literal = getLiteral(lexerAtomContext.terminal().STRING_LITERAL());
Integer tokenType = tokenTypesByLiteral.get(literal);
if (tokenType == null)
tokenType = 0;
return new LiteralElementSpec(label, multiplicity, tokenType, literal);
}
} else if (lexerAtomContext.RULE_REF() != null) {
return new RuleRefElementSpec(this, label, multiplicity, lexerAtomContext.RULE_REF().getText());
} else if (lexerAtomContext.notSet() != null
|| lexerAtomContext.DOT() != null
|| lexerAtomContext.LEXER_CHAR_SET()!=null
|| lexerAtomContext.range() != null) {
// Use AnyTokenElementSpec here to as it does not affect our code assist analysis
return new AnyTokenElementSpec(label, multiplicity);
} else {
throw new IllegalStateException();
}
}
private Set<Integer> getNegativeTokenTypes(NotSetContext notSetContext) {
Set<Integer> negativeTokenTypes = new HashSet<>();
if (notSetContext.setElement() != null) {
negativeTokenTypes.add(getTokenType(notSetContext.setElement()));
} else {
for (SetElementContext setElementContext: notSetContext.blockSet().setElement())
negativeTokenTypes.add(getTokenType(setElementContext));
}
return negativeTokenTypes;
}
private int getTokenType(SetElementContext setElementContext) {
Integer tokenType;
if (setElementContext.STRING_LITERAL() != null)
tokenType = tokenTypesByLiteral.get(getLiteral(setElementContext.STRING_LITERAL()));
else if (setElementContext.TOKEN_REF() != null)
tokenType = tokenTypesByRule.get(setElementContext.TOKEN_REF().getText());
else
tokenType = null;
if (tokenType != null)
return tokenType;
else
throw new IllegalStateException();
}
private Multiplicity newMultiplicity(@Nullable EbnfSuffixContext ebnfSuffixContext) {
if (ebnfSuffixContext != null) {
if (ebnfSuffixContext.STAR() != null)
return Multiplicity.ZERO_OR_MORE;
else if (ebnfSuffixContext.PLUS() != null)
return Multiplicity.ONE_OR_MORE;
else
return Multiplicity.ZERO_OR_ONE;
} else {
return Multiplicity.ONE;
}
}
private ElementSpec newElement(@Nullable String label, BlockContext blockContext, @Nullable EbnfSuffixContext ebnfSuffixContext) {
List<AlternativeSpec> alternatives = new ArrayList<>();
for (AlternativeContext alternativeContext: blockContext.altList().alternative())
alternatives.add(newAltenative(null, alternativeContext));
String ruleName = UUID.randomUUID().toString();
blockRuleNames.add(ruleName);
RuleSpec rule = new RuleSpec(ruleName, alternatives);
rules.put(ruleName, rule);
return new RuleRefElementSpec(this, label, newMultiplicity(ebnfSuffixContext), ruleName);
}
private ElementSpec newElement(@Nullable String label, LexerBlockContext lexerBlockContext, @Nullable EbnfSuffixContext ebnfSuffixContext) {
List<AlternativeSpec> alternatives = new ArrayList<>();
for (LexerAltContext lexerAltContext: lexerBlockContext.lexerAltList().lexerAlt())
alternatives.add(newAltenative(lexerAltContext));
String ruleName = UUID.randomUUID().toString();
blockRuleNames.add(ruleName);
RuleSpec rule = new RuleSpec(ruleName, alternatives);
rules.put(ruleName, rule);
return new RuleRefElementSpec(this, label, newMultiplicity(ebnfSuffixContext), ruleName);
}
private ElementSpec newElement(EbnfContext ebnfContext) {
if (ebnfContext.blockSuffix() != null)
return newElement(null, ebnfContext.block(), ebnfContext.blockSuffix().ebnfSuffix());
else
return newElement(null, ebnfContext.block(), null);
}
public boolean isBlockRule(String ruleName) {
return blockRuleNames.contains(ruleName);
}
@Nullable
public String getTokenNameByType(int tokenType) {
for (Map.Entry<String, Integer> entry: tokenTypesByRule.entrySet()) {
if (entry.getValue() == tokenType)
return entry.getKey();
}
return null;
}
@Nullable
public Integer getTokenTypeByLiteral(String literal) {
return tokenTypesByLiteral.get(literal);
}
@Nullable
public RuleSpec getRule(String ruleName) {
return rules.get(ruleName);
}
public final List<Token> lex(String content) {
try {
List<Token> tokens = new ArrayList<>();
Lexer lexer = getLexerCtor().newInstance(new ANTLRInputStream(content));
lexer.removeErrorListeners();
Token token = lexer.nextToken();
while (token.getType() != Token.EOF) {
if (token.getChannel() == Token.DEFAULT_CHANNEL)
tokens.add(token);
token = lexer.nextToken();
}
return tokens;
} catch (InstantiationException | IllegalAccessException | IllegalArgumentException
| InvocationTargetException e) {
throw new RuntimeException(e);
}
}
}

View File

@ -1,70 +0,0 @@
package com.gitplex.commons.antlr.grammar;
import java.util.Set;
import com.gitplex.commons.antlr.codeassist.MandatoryScan;
import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
import com.google.common.collect.Sets;
public class LexerRuleRefElementSpec extends TokenElementSpec {
private static final long serialVersionUID = 1L;
private final Grammar grammar;
private final String ruleName;
private transient Optional<RuleSpec> rule;
public LexerRuleRefElementSpec(Grammar grammar, String label, Multiplicity multiplicity,
int tokenType, String ruleName) {
super(label, multiplicity, tokenType);
this.grammar = grammar;
this.ruleName = ruleName;
}
public String getRuleName() {
return ruleName;
}
public RuleSpec getRule() {
if (rule == null)
rule = Optional.fromNullable(grammar.getRule(ruleName));
return rule.orNull();
}
@Override
public MandatoryScan scanMandatories() {
if (getRule() != null)
return getRule().scanMandatories();
else
return MandatoryScan.stop();
}
@Override
protected String toStringOnce() {
if (grammar.isBlockRule(ruleName))
return "(" + Preconditions.checkNotNull(getRule()) + ")";
else
return ruleName;
}
@Override
public Set<String> getPossiblePrefixes() {
if (getRule() != null)
return getRule().getPossiblePrefixes();
else
return Sets.newLinkedHashSet();
}
@Override
protected boolean isAllowEmptyOnce() {
if (getRule() != null)
return getRule().isAllowEmpty();
else
return false;
}
}

View File

@ -1,48 +0,0 @@
package com.gitplex.commons.antlr.grammar;
import java.util.LinkedHashSet;
import java.util.Set;
import com.gitplex.commons.antlr.codeassist.MandatoryScan;
import com.google.common.collect.Lists;
public class LiteralElementSpec extends TokenElementSpec {
private static final long serialVersionUID = 1L;
private final String literal;
public LiteralElementSpec(String label, Multiplicity multiplicity,
int tokenType, String literal) {
super(label, multiplicity, tokenType);
this.literal = literal;
}
public String getLiteral() {
return literal;
}
@Override
public MandatoryScan scanMandatories() {
return new MandatoryScan(Lists.newArrayList(literal), false);
}
@Override
protected String toStringOnce() {
return "'" + literal + "'";
}
@Override
public Set<String> getPossiblePrefixes() {
Set<String> possiblePrefixes = new LinkedHashSet<>();
possiblePrefixes.add(literal);
return possiblePrefixes;
}
@Override
protected boolean isAllowEmptyOnce() {
return false;
}
}

View File

@ -1,61 +0,0 @@
package com.gitplex.commons.antlr.grammar;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import org.apache.commons.lang3.StringUtils;
import com.gitplex.commons.antlr.codeassist.MandatoryScan;
import com.google.common.base.Preconditions;
import com.google.common.collect.Sets;
public class NotTokenElementSpec extends TerminalElementSpec {
private static final long serialVersionUID = 1L;
private final Grammar grammar;
private final Set<Integer> notTokenTypes;
public NotTokenElementSpec(Grammar grammar, String label,
Multiplicity multiplicity, Set<Integer> notTokenTypes) {
super(label, multiplicity);
this.grammar = grammar;
this.notTokenTypes = notTokenTypes;
}
public Set<Integer> getNotTokenTypes() {
return notTokenTypes;
}
@Override
public MandatoryScan scanMandatories() {
return MandatoryScan.stop();
}
@Override
protected String toStringOnce() {
List<String> notTokenNames = new ArrayList<>();
for (int notTokenType: notTokenTypes)
notTokenNames.add(Preconditions.checkNotNull(grammar.getTokenNameByType(notTokenType)));
return StringUtils.join(notTokenNames, " ");
}
@Override
public Set<String> getPossiblePrefixes() {
return Sets.newLinkedHashSet();
}
@Override
protected boolean isAllowEmptyOnce() {
return false;
}
@Override
public boolean isToken(int tokenType) {
return !notTokenTypes.contains(tokenType);
}
}

View File

@ -1,67 +0,0 @@
package com.gitplex.commons.antlr.grammar;
import java.util.List;
import java.util.Set;
import org.antlr.v4.runtime.Token;
import com.gitplex.commons.antlr.codeassist.MandatoryScan;
import com.gitplex.commons.antlr.parser.EarleyParser;
import com.google.common.base.Preconditions;
public class RuleRefElementSpec extends ElementSpec {
private static final long serialVersionUID = 1L;
private final Grammar grammar;
private final String ruleName;
private transient RuleSpec rule;
public RuleRefElementSpec(Grammar grammar, String label, Multiplicity multiplicity, String ruleName) {
super(label, multiplicity);
this.grammar = grammar;
this.ruleName = ruleName;
}
public RuleSpec getRule() {
if (rule == null)
rule = Preconditions.checkNotNull(grammar.getRule(ruleName));
return rule;
}
public String getRuleName() {
return ruleName;
}
@Override
public MandatoryScan scanMandatories() {
return getRule().scanMandatories();
}
@Override
protected String toStringOnce() {
if (grammar.isBlockRule(ruleName))
return "(" + Preconditions.checkNotNull(getRule()) + ")";
else
return ruleName;
}
@Override
public int getEndOfMatch(List<Token> tokens) {
return new EarleyParser(getRule(), tokens).getEndOfMatch();
}
@Override
public Set<String> getPossiblePrefixes() {
return getRule().getPossiblePrefixes();
}
@Override
protected boolean isAllowEmptyOnce() {
return getRule().isAllowEmpty();
}
}

View File

@ -1,141 +0,0 @@
package com.gitplex.commons.antlr.grammar;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import org.apache.commons.lang3.StringUtils;
import com.gitplex.commons.antlr.codeassist.MandatoryScan;
import com.gitplex.commons.antlr.grammar.ElementSpec.Multiplicity;
public class RuleSpec implements Serializable {
private static final long serialVersionUID = 1L;
private final String name;
private final List<AlternativeSpec> alternatives;
private Set<String> possiblePrefixes;
private Boolean allowEmpty;
private MandatoryScan mandatoryScan;
public RuleSpec(String name, List<AlternativeSpec> alternatives) {
this.name = name;
this.alternatives = alternatives;
}
public String getName() {
return name;
}
public List<AlternativeSpec> getAlternatives() {
return alternatives;
}
private MandatoryScan doScanMandatories() {
List<AlternativeSpec> alternatives = getAlternatives();
// nothing will be mandatory if we have multiple alternatives
if (alternatives.size() == 1) {
List<String> mandatories = new ArrayList<>();
for (ElementSpec elementSpec: alternatives.get(0).getElements()) {
if (elementSpec.getMultiplicity() == Multiplicity.ZERO_OR_ONE
|| elementSpec.getMultiplicity() == Multiplicity.ZERO_OR_MORE) {
// next input can either be current element, or other elements, so
// mandatory scan can be stopped
return new MandatoryScan(mandatories, true);
} else if (elementSpec.getMultiplicity() == Multiplicity.ONE_OR_MORE) {
MandatoryScan scan = elementSpec.scanMandatories();
mandatories.addAll(scan.getMandatories());
// next input can either be current element, or other elements, so
// mandatory scan can be stopped
return new MandatoryScan(mandatories, true);
} else {
MandatoryScan scan = elementSpec.scanMandatories();
mandatories.addAll(scan.getMandatories());
// if internal of the element tells use to stop, let's stop
if (scan.isStop())
return new MandatoryScan(mandatories, true);
}
}
return new MandatoryScan(mandatories, false);
} else {
return MandatoryScan.stop();
}
}
public MandatoryScan scanMandatories() {
if (mandatoryScan == null) {
// initialize this to return a meaningful value in case this method is
// invoked recursively
mandatoryScan = MandatoryScan.stop();
mandatoryScan = doScanMandatories();
}
return mandatoryScan;
}
private Set<String> doGetPossiblePrefixes() {
Set<String> possiblePrefixes = new LinkedHashSet<>();
for (AlternativeSpec alternative: alternatives) {
for (ElementSpec elementSpec: alternative.getElements()) {
possiblePrefixes.addAll(elementSpec.getPossiblePrefixes());
if (!elementSpec.isAllowEmpty())
break;
}
}
return possiblePrefixes;
}
public Set<String> getPossiblePrefixes() {
if (possiblePrefixes == null) {
// initialize this to return a meaningful value in case this method is
// invoked recursively
possiblePrefixes = new LinkedHashSet<>();
possiblePrefixes = doGetPossiblePrefixes();
}
return possiblePrefixes;
}
private boolean doIsAllowEmpty() {
for (AlternativeSpec alternative: getAlternatives()) {
boolean allowEmpty = true;
for (ElementSpec elementSpec: alternative.getElements()) {
if (!elementSpec.isAllowEmpty()) {
allowEmpty = false;
break;
}
}
if (allowEmpty)
return true;
}
return false;
}
public boolean isAllowEmpty() {
if (allowEmpty == null) {
// initialize this to return a meaningful value in case this method is
// invoked recursively
allowEmpty = false;
allowEmpty = doIsAllowEmpty();
}
return allowEmpty;
}
@Override
public String toString() {
List<String> alternativeStrings = new ArrayList<>();
for (AlternativeSpec alternative: alternatives)
alternativeStrings.add(alternative.toString());
return StringUtils.join(alternativeStrings, " | ");
}
}

View File

@ -1,25 +0,0 @@
package com.gitplex.commons.antlr.grammar;
import java.util.List;
import org.antlr.v4.runtime.Token;
public abstract class TerminalElementSpec extends ElementSpec {
private static final long serialVersionUID = 1L;
public TerminalElementSpec(String label, Multiplicity multiplicity) {
super(label, multiplicity);
}
public abstract boolean isToken(int tokenType);
@Override
public int getEndOfMatch(List<Token> tokens) {
if (!tokens.isEmpty() && isToken(tokens.get(0).getType()))
return 1;
else
return -1;
}
}

View File

@ -1,24 +0,0 @@
package com.gitplex.commons.antlr.grammar;
public abstract class TokenElementSpec extends TerminalElementSpec {
private static final long serialVersionUID = 1L;
private final int tokenType;
public TokenElementSpec(String label, Multiplicity multiplicity, int tokenType) {
super(label, multiplicity);
this.tokenType = tokenType;
}
public int getTokenType() {
return tokenType;
}
@Override
public boolean isToken(int tokenType) {
return tokenType == this.tokenType;
}
}

View File

@ -1,117 +0,0 @@
package com.gitplex.commons.antlr.parser;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import javax.annotation.Nullable;
import org.antlr.v4.runtime.Token;
import com.gitplex.commons.antlr.grammar.ElementSpec;
import com.gitplex.commons.antlr.grammar.TerminalElementSpec;
/**
* Represent a chart (or state set) as mentioned in https://en.wikipedia.org/wiki/Earley_parser
*
* @author robin
*
*/
public class Chart {
private final EarleyParser parser;
private final int position;
private final Set<State> states;
/**
* Construct a Earley chart.
*
* @param parser
* current Earley parser instance
* @param position
* position of the chart, representing index of next token to be matched for this chart
* @param states
* states in this chart
*/
public Chart(EarleyParser parser, int endTokenIndex, Set<State> states) {
this.parser = parser;
this.position = endTokenIndex;
this.states = states;
}
public EarleyParser getParser() {
return parser;
}
/**
* Get position of this chart
*
* @return
* position of the chart, representing index of next token to be matched for this chart
*/
public int getPosition() {
return position;
}
/**
* Get the token being scanned to create this chart.
*
* @return
* the token being scanned to create this chart, or <tt>null</tt> for initial chart
*/
@Nullable
public Token getOriginatingToken() {
if (position > 0)
return parser.getTokens().get(position-1);
else
return null;
}
/**
* Get set of states in this chart
*
* @return
* set of states in this chart
*/
public Set<State> getStates() {
return states;
}
/**
* Get matched states in this chart.
*
* @return
* matched states in this chart
*/
public List<State> getMatches() {
List<State> matches = new ArrayList<>();
for (State state: states) {
if (state.getRuleSpec().getName().equals(parser.getRule().getName())
&& state.getOriginPosition() == 0 && state.isCompleted()) {
matches.add(state);
}
}
return matches;
}
public List<State> getStatesExpectingTerminal() {
List<State> statesExpectingTerminal = new ArrayList<>();
for (State state: states) {
ElementSpec expectingSpec = state.getExpectedElementSpec();
if (expectingSpec instanceof TerminalElementSpec)
statesExpectingTerminal.add(state);
}
return statesExpectingTerminal;
}
@Override
public String toString() {
StringBuffer buffer = new StringBuffer();
for (State state: states)
buffer.append(state).append("\n");
return buffer.toString();
}
}

View File

@ -1,199 +0,0 @@
package com.gitplex.commons.antlr.parser;
import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import javax.annotation.Nullable;
import org.antlr.v4.runtime.Token;
import com.gitplex.commons.antlr.grammar.ElementSpec;
import com.gitplex.commons.antlr.grammar.RuleRefElementSpec;
import com.gitplex.commons.antlr.grammar.RuleSpec;
import com.gitplex.commons.antlr.grammar.TerminalElementSpec;
import com.google.common.collect.Lists;
/**
* A Earley parser (https://en.wikipedia.org/wiki/Earley_parser) to parse user inputs.
* It is very suited for code assistance purpose as it can provide partial
* parse results and tell us what terminals are expected next. Note that for large
* inputs (thousands of lines for example), our earley implementation performs bad
* and consumes a lot of memory, but it serves our purpose to provide a mini code
* assistance for web input
*
* @author robin
*
*/
public class EarleyParser {
private final RuleSpec rule;
private final List<Token> tokens;
private int tokenIndex = 0;
private final List<Chart> charts = new ArrayList<>();
public EarleyParser(RuleSpec rule, List<Token> tokens) {
this.rule = rule;
this.tokens = tokens;
Set<State> states = new LinkedHashSet<>();
for (int i=0; i<rule.getAlternatives().size(); i++)
states.add(new State(tokenIndex, rule, i, 0, false, new ArrayList<Element>()));
while (!states.isEmpty()) {
Chart chart = new Chart(this, tokenIndex, states);
charts.add(chart);
for (State state: Lists.newArrayList(chart.getStates())) // avoid concurrent modification
process(state, chart);
if (tokenIndex == tokens.size())
break;
states = new LinkedHashSet<>();
for (State state: chart.getStates())
scan(state, states);
tokenIndex++;
}
}
private void process(State state, Chart chart) {
if (!state.isCompleted()) { // predict
ElementSpec expectedElementSpec = state.getExpectedElementSpec();
if (expectedElementSpec instanceof RuleRefElementSpec) {
RuleRefElementSpec ruleRefElement = (RuleRefElementSpec) expectedElementSpec;
RuleSpec elementRule = ruleRefElement.getRule();
for (int i=0; i<elementRule.getAlternatives().size(); i++) {
State predictedState = new State(tokenIndex,
elementRule, i, 0, false, new ArrayList<Element>());
if (chart.getStates().add(predictedState))
process(predictedState, chart);
}
}
if (expectedElementSpec.isOptional() || state.isExpectedElementSpecMatchedOnce()) {
State advancedState = new State(state.getOriginPosition(), state.getRuleSpec(),
state.getAlternativeSpecIndex(), state.getExpectedElementSpecIndex()+1, false,
new ArrayList<>(state.getElements()));
if (chart.getStates().add(advancedState))
process(advancedState, chart);
}
} else { // complete
Chart startChart = charts.get(state.getOriginPosition());
Collection<State> startStates;
if (state.getOriginPosition() == chart.getPosition())
startStates = Lists.newArrayList(startChart.getStates()); // avoid concurrent modification
else
startStates = startChart.getStates();
for (State startState: startStates) {
if (!startState.isCompleted()) {
ElementSpec expectedElementSpec = startState.getExpectedElementSpec();
if (expectedElementSpec instanceof RuleRefElementSpec) {
RuleRefElementSpec ruleRefElement = (RuleRefElementSpec) expectedElementSpec;
if (ruleRefElement.getRuleName().equals(state.getRuleSpec().getName())) {
State advancedState;
List<Element> elements = new ArrayList<>(startState.getElements());
if (!state.getElements().isEmpty())
elements.add(new Element(this, ruleRefElement, chart.getPosition(), state));
if (!expectedElementSpec.isMultiple()) {
advancedState = new State(startState.getOriginPosition(),
startState.getRuleSpec(), startState.getAlternativeSpecIndex(),
startState.getExpectedElementSpecIndex()+1, false, elements);
} else {
advancedState = new State(startState.getOriginPosition(),
startState.getRuleSpec(), startState.getAlternativeSpecIndex(),
startState.getExpectedElementSpecIndex(), true, elements);
}
if (chart.getStates().add(advancedState))
process(advancedState, chart);
}
}
}
}
}
}
private void scan(State state, Set<State> nextStates) {
if (!state.isCompleted()) {
ElementSpec expectedElementSpec = state.getExpectedElementSpec();
int tokenType = tokens.get(tokenIndex).getType();
if ((expectedElementSpec instanceof TerminalElementSpec)
&& ((TerminalElementSpec)expectedElementSpec).isToken(tokenType)) {
State scannedState;
List<Element> elements = new ArrayList<>(state.getElements());
elements.add(new Element(this, expectedElementSpec, tokenIndex+1, null));
if (!expectedElementSpec.isMultiple()) {
scannedState = new State(state.getOriginPosition(), state.getRuleSpec(),
state.getAlternativeSpecIndex(), state.getExpectedElementSpecIndex()+1,
false, elements);
} else {
scannedState = new State(state.getOriginPosition(), state.getRuleSpec(),
state.getAlternativeSpecIndex(), state.getExpectedElementSpecIndex(),
true, elements);
}
nextStates.add(scannedState);
}
}
}
public List<Chart> getCharts() {
return charts;
}
public RuleSpec getRule() {
return rule;
}
public List<Token> getTokens() {
return tokens;
}
public List<State> getMatches() {
if (charts.size() == tokens.size()+1)
return charts.get(tokens.size()).getMatches();
else
return new ArrayList<>();
}
public boolean matches() {
return !getMatches().isEmpty();
}
@Nullable
public Token getLastMatchedToken() {
int endOfMatch = getEndOfMatch();
if (endOfMatch > 0)
return tokens.get(endOfMatch-1);
else
return null;
}
public List<Token> getMatchedTokens() {
int endOfMatch = getEndOfMatch();
if (endOfMatch > 0)
return tokens.subList(0, endOfMatch);
else
return new ArrayList<>();
}
/**
* Get the next token index after the match.
*
* @param tokens
* tokens to match against
* @return
* index of next token after the match, or 0 if the rule does not match any tokens
*/
public int getEndOfMatch() {
for (int i=charts.size()-1; i>=0; i--) {
Chart state = charts.get(i);
if (!state.getMatches().isEmpty())
return i;
}
return 0;
}
}

View File

@ -1,216 +0,0 @@
package com.gitplex.commons.antlr.parser;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.Nullable;
import org.antlr.v4.runtime.Token;
import com.gitplex.commons.antlr.grammar.ElementSpec;
/**
* Represent a matched element.
*
* @author robin
*
*/
public class Element {
private final ElementSpec spec;
private final int position;
private final State state;
private final EarleyParser parser;
public Element(EarleyParser parser, @Nullable ElementSpec spec, int position, @Nullable State state) {
this.parser = parser;
this.spec = spec;
this.position = position;
this.state = state;
}
/**
* Get spec of this element
*
* @return
* spec of this element, or <tt>null</tt> for root element, as root element
* is a pseudo element wrapping the root state
*/
@Nullable
public ElementSpec getSpec() {
return spec;
}
public boolean isRoot() {
return spec == null;
}
public boolean isTerminal() {
return state == null;
}
/**
* Get label of this element defined in grammar
*
* @return
* label of this element, or <tt>null</tt> if there is no label associated
* with the element
*/
@Nullable
public String getLabel() {
return spec!=null?spec.getLabel():null;
}
/**
* Get position of the chart the element is matched in
*
* @return
* position of the chart the element is matched in. It also represents index of
* next token after matching of this element
*/
public int getPosition() {
return position;
}
/**
* Get associated state of the element
*
* @return
* associated state of the element, or <tt>null</tt> if this element represents
* a terminal element which will be created by scanning a matched token
*/
@Nullable
public State getState() {
return state;
}
/**
* Get tokens matched by this element so far.
*
* @return
* tokens matched by this element so far, or empty if this element does not
* match any tokens yet
*/
public List<Token> getMatchedTokens() {
if (state != null)
return parser.getTokens().subList(state.getOriginPosition(), position);
else if (position > 0)
return parser.getTokens().subList(position-1, position);
else
return new ArrayList<>();
}
/**
* Get the first token matched by this element.
*
* @return
* first token matched by this element, or <tt>null</tt> if this element
* does not match any tokens yet
*/
@Nullable
public Token getFirstMatchedToken() {
if (state != null) {
if (position > state.getOriginPosition())
return parser.getTokens().get(state.getOriginPosition());
else
return null;
} else if (position > 0) {
return parser.getTokens().get(position-1);
} else {
return null;
}
}
/**
* Get the last token matched by this element.
*
* @return
* last token matched by this element, or <tt>null</tt> if this element does not
* match any tokens yet
*/
@Nullable
public Token getLastMatchedToken() {
if (state != null) {
if (position > state.getOriginPosition())
return parser.getTokens().get(position-1);
else
return null;
} else if (position > 0) {
return parser.getTokens().get(position-1);
} else {
return null;
}
}
public String getMatchedText() {
StringBuilder builder = new StringBuilder();
for (Token token: getMatchedTokens())
builder.append(token.getText());
return builder.toString();
}
/**
* Find children by label defined in grammar
*
* @param label
* element label defined in grammar
* @param recursive
* whether or not search recursively
* @return
* list of children with specified label
*/
public List<Element> findChildrenByLabel(String label, boolean recursive) {
List<Element> children = new ArrayList<>();
if (state != null) {
for (Element child: state.getElements()) {
if (label.equals(child.getLabel()))
children.add(child);
if (recursive)
children.addAll(child.findChildrenByLabel(label, recursive));
}
}
return children;
}
/**
* Find children by rule name
*
* @param ruleName
* name of the rule
* @param recursive
* whether or not search recursively
* @return
* list of children with specified rule name
*/
public List<Element> findChildrenByRule(String ruleName, boolean recursive) {
List<Element> children = new ArrayList<>();
if (state != null) {
for (Element child: state.getElements()) {
if (child.getState() != null && ruleName.equals(child.getState().getRuleSpec().getName()))
children.add(child);
if (recursive)
children.addAll(child.findChildrenByRule(ruleName, recursive));
}
}
return children;
}
public EarleyParser getParser() {
return parser;
}
@Override
public String toString() {
StringBuilder builder = new StringBuilder("(");
if (spec != null)
builder.append("spec: " + spec + ", ");
if (state != null)
builder.append("state: " + state + ", ");
builder.append("endTokenIndex: " + position + ")");
return builder.toString();
}
}

View File

@ -1,197 +0,0 @@
package com.gitplex.commons.antlr.parser;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.Nullable;
import org.apache.commons.lang3.builder.EqualsBuilder;
import org.apache.commons.lang3.builder.HashCodeBuilder;
import com.gitplex.commons.antlr.grammar.AlternativeSpec;
import com.gitplex.commons.antlr.grammar.ElementSpec;
import com.gitplex.commons.antlr.grammar.RuleSpec;
/**
* Represents a Earley state as mentioned in https://en.wikipedia.org/wiki/Earley_parser
*
* @author robin
*
*/
public class State {
private final int originPosition;
private final RuleSpec ruleSpec;
private final int alternativeSpecIndex;
private final int expectedElementSpecIndex;
private final boolean expectedElementSpecMatchedOnce;
private final List<Element> elements;
private transient AlternativeSpec alternativeSpec;
private transient List<ElementSpec> elementSpecs;
/**
* Construct a Earley state.
*
* @param originPosition
* position of the chart originating this state. Representing index of first token matched by the state
* @param ruleSpec
* rule spec of the state
* @param alternativeSpecIndex
* index of alternative spec above rule
* @param expectedElementSpecIndex
* index of element spec expecting to be matched, representing dot position
* of the state
* @param expectedElementSpecMatchedOnce
* whether or not the expected element spec has been matched at least once to
* facilitate handling of element multiplicity (* and +)
* @param elements
* already matched elements in this state
*/
public State(int originPosition, RuleSpec ruleSpec, int alternativeSpecIndex, int expectedElementSpecIndex,
boolean expectedElementSpecMatchedOnce, List<Element> elements) {
this.originPosition = originPosition;
this.ruleSpec = ruleSpec;
this.alternativeSpecIndex = alternativeSpecIndex;
this.expectedElementSpecIndex = expectedElementSpecIndex;
this.expectedElementSpecMatchedOnce = expectedElementSpecMatchedOnce;
this.elements = elements;
}
/**
* Get origin position of this state
*
* @return
* position of the chart originating this state. Representing index of first token matched by the state
*/
public int getOriginPosition() {
return originPosition;
}
public RuleSpec getRuleSpec() {
return ruleSpec;
}
public int getAlternativeSpecIndex() {
return alternativeSpecIndex;
}
public int getExpectedElementSpecIndex() {
return expectedElementSpecIndex;
}
public boolean isExpectedElementSpecMatchedOnce() {
return expectedElementSpecMatchedOnce;
}
/**
* Get expected element spec
*
* @return
* element spec expected to be matched next, or <tt>null</tt> if
* the state is completed
*/
@Nullable
public ElementSpec getExpectedElementSpec() {
if (isCompleted())
return null;
else
return getElementSpecs().get(expectedElementSpecIndex);
}
/**
* Get elements already matched in this state
*
* @return
* elements already matched in this state
*/
public List<Element> getElements() {
return elements;
}
public AlternativeSpec getAlternativeSpec() {
if (alternativeSpec == null)
alternativeSpec = ruleSpec.getAlternatives().get(alternativeSpecIndex);
return alternativeSpec;
}
public List<ElementSpec> getElementSpecs() {
if (elementSpecs == null)
elementSpecs = getAlternativeSpec().getElements();
return elementSpecs;
}
public boolean isCompleted() {
return expectedElementSpecIndex == getElementSpecs().size();
}
public State getScannedState(EarleyParser parser, int tokenIndex) {
ElementSpec expectedElementSpec = getExpectedElementSpec();
List<Element> elements = new ArrayList<>(getElements());
elements.add(new Element(parser, expectedElementSpec, tokenIndex+1, null));
if (!expectedElementSpec.isMultiple()) {
return new State(getOriginPosition(), getRuleSpec(),
getAlternativeSpecIndex(), getExpectedElementSpecIndex()+1,
false, elements);
} else {
return new State(getOriginPosition(), getRuleSpec(),
getAlternativeSpecIndex(), getExpectedElementSpecIndex(),
true, elements);
}
}
@Override
public boolean equals(Object other) {
if (!(other instanceof State))
return false;
if (this == other)
return true;
State otherState = (State) other;
/*
* The standard Earley parser should also consider parsed elements into
* account when compare state, however it will cause state to increase
* quickly in case of ambiguity rules. By excluding parsed elements from
* comparison, we normally get only the first possibility amongst all
* the ambiguity possibilities, which is totally acceptable for our
* code assistance purpose
*/
return new EqualsBuilder()
.append(originPosition, otherState.originPosition)
.append(ruleSpec.getName(), otherState.ruleSpec.getName())
.append(alternativeSpecIndex, otherState.alternativeSpecIndex)
.append(expectedElementSpecIndex, otherState.expectedElementSpecIndex)
.append(expectedElementSpecMatchedOnce, otherState.expectedElementSpecMatchedOnce)
.isEquals();
}
@Override
public int hashCode() {
return new HashCodeBuilder(17, 37)
.append(originPosition)
.append(ruleSpec.getName())
.append(alternativeSpecIndex)
.append(expectedElementSpecIndex)
.append(expectedElementSpecMatchedOnce)
.toHashCode();
}
@Override
public String toString() {
StringBuffer buffer = new StringBuffer();
for (int i=0; i<expectedElementSpecIndex; i++)
buffer.append(getElementSpecs().get(i)).append(" ");
buffer.append(expectedElementSpecMatchedOnce?"~ ":"^ ");
for (int i=expectedElementSpecIndex; i<getElementSpecs().size(); i++)
buffer.append(getElementSpecs().get(i)).append(" ");
return ruleSpec.getName() + " -> " + buffer.toString() + ": " + originPosition;
}
}

View File

@ -1,17 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<archetype-descriptor name="archetype.plugin">
<fileSets>
<fileSet filtered="true" packaged="true">
<directory>src/main/java</directory>
</fileSet>
<fileSet filtered="false" packaged="false">
<directory>src/main/resources</directory>
</fileSet>
<fileSet filtered="false" packaged="false">
<directory>src/test/java</directory>
</fileSet>
<fileSet filtered="false" packaged="false">
<directory>src/test/resources</directory>
</fileSet>
</fileSets>
</archetype-descriptor>

View File

@ -1,60 +0,0 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
#if (\${groupId} != "com.gitplex")
<groupId>\${groupId}</groupId>
#end
<artifactId>\${artifactId}</artifactId>
<version>\${version}</version>
<parent>
<groupId>com.gitplex</groupId>
<artifactId>parent.general</artifactId>
<version>1.0.0</version>
</parent>
<build>
<plugins>
<plugin>
<groupId>com.gitplex</groupId>
<artifactId>plugin-maven</artifactId>
</plugin>
<plugin>
<artifactId>maven-source-plugin</artifactId>
</plugin>
<plugin>
<artifactId>maven-javadoc-plugin</artifactId>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>${project.artifactId}</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
<repositories>
<repository>
<id>pmeaseRepo</id>
<name>PMEase Repository</name>
<releases>
<enabled>true</enabled>
<updatePolicy>never</updatePolicy>
<checksumPolicy>fail</checksumPolicy>
</releases>
<snapshots>
<enabled>true</enabled>
<updatePolicy>always</updatePolicy>
<checksumPolicy>fail</checksumPolicy>
</snapshots>
<url>http://artifact.pmease.com/</url>
</repository>
</repositories>
<properties>
<moduleClass>\${package}.PluginModule</moduleClass>
</properties>
</project>

View File

@ -1,19 +0,0 @@
package ${package};
import com.gitplex.calla.loader.AbstractPlugin;
import com.gitplex.calla.loader.AbstractPluginModule;
/**
* NOTE: Do not forget to rename moduleClass property defined in the pom if you've renamed this class.
*
*/
public class PluginModule extends AbstractPluginModule {
@Override
protected void configure() {
super.configure();
// put your guice bindings here
}
}

View File

@ -1,46 +0,0 @@
package com.gitplex.commons.antlr.codeassist;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import org.junit.Test;
import com.gitplex.commons.antlr.codeassist.test.CodeAssistTest1Lexer;
import com.gitplex.commons.antlr.codeassist.test.CodeAssistTest4Lexer;
import com.gitplex.commons.antlr.codeassist.test.CodeAssistTest6Lexer;
import com.gitplex.commons.antlr.grammar.Grammar;
import com.gitplex.commons.antlr.parser.EarleyParser;
public class EarleyParserTest {
private Grammar grammar;
private boolean matches(String ruleName, String text) {
return new EarleyParser(grammar.getRule(ruleName), grammar.lex(text)).matches();
}
@Test
public void test() {
grammar = new Grammar(CodeAssistTest1Lexer.class);
assertFalse(matches("notRealAmbiguity", "1"));
assertTrue(matches("notRealAmbiguity", "1 2"));
assertTrue(matches("notRealAmbiguity", "1 2 3"));
grammar = new Grammar(CodeAssistTest4Lexer.class);
assertTrue(matches("expr", "(1+2)+3"));
assertTrue(matches("expr", "1+(2*3)"));
assertFalse(matches("expr", "(1+2)+"));
assertFalse(matches("expr", "1(2*3)"));
assertFalse(matches("expr", "1/2+3)"));
grammar = new Grammar(CodeAssistTest6Lexer.class);
assertTrue(matches("compilationUnit", ""));
assertTrue(matches("compilationUnit", ""
+ "public class A {"
+ " public static void main(String[] args) {"
+ " System.out.println(\"hello world\");"
+ " }"
+ "}"));
}
}

View File

@ -1,63 +0,0 @@
package com.gitplex.commons.antlr.codeassist;
import static org.junit.Assert.assertEquals;
import java.util.ArrayList;
import java.util.List;
import org.junit.Test;
import com.gitplex.commons.antlr.codeassist.CodeAssist;
import com.gitplex.commons.antlr.codeassist.InputCompletion;
import com.gitplex.commons.antlr.codeassist.InputStatus;
import com.gitplex.commons.antlr.codeassist.InputSuggestion;
import com.gitplex.commons.antlr.codeassist.ParentedElement;
import com.gitplex.commons.antlr.codeassist.test.CodeAssistTest1Lexer;
public class TestCodeAssist1 {
private CodeAssist codeAssist = new CodeAssist(CodeAssistTest1Lexer.class) {
private static final long serialVersionUID = 1L;
@Override
protected List<InputSuggestion> suggest(ParentedElement element, String matchWith, int count) {
return null;
}
};
private List<InputStatus> suggest(InputStatus inputStatus, String ruleName) {
List<InputStatus> suggestions = new ArrayList<>();
for (InputCompletion completion: codeAssist.suggest(inputStatus, ruleName, Integer.MAX_VALUE))
suggestions.add(completion.complete(inputStatus));
return suggestions;
}
@Test
public void test() {
List<InputStatus> suggestions;
suggestions = suggest(new InputStatus(""), "selfReference");
assertEquals(1, suggestions.size());
assertEquals("ab:2", suggestions.get(0).toString());
suggestions = suggest(new InputStatus("ab"), "selfReference");
assertEquals(0, suggestions.size());
suggestions = suggest(new InputStatus("ab "), "selfReference");
assertEquals(1, suggestions.size());
assertEquals("ab cd:5", suggestions.get(0).toString());
suggestions = suggest(new InputStatus(""), "mandatories");
assertEquals(2, suggestions.size());
assertEquals("ab c:4", suggestions.get(0).toString());
assertEquals("cd ef g h:9", suggestions.get(1).toString());
suggestions = suggest(new InputStatus("cd "), "mandatories");
assertEquals(1, suggestions.size());
assertEquals("cd ef g h:9", suggestions.get(0).toString());
}
}

View File

@ -1,130 +0,0 @@
package com.gitplex.commons.antlr.codeassist;
import static org.junit.Assert.assertEquals;
import java.util.ArrayList;
import java.util.List;
import org.junit.Test;
import com.gitplex.commons.antlr.codeassist.CodeAssist;
import com.gitplex.commons.antlr.codeassist.FenceAware;
import com.gitplex.commons.antlr.codeassist.InputCompletion;
import com.gitplex.commons.antlr.codeassist.InputStatus;
import com.gitplex.commons.antlr.codeassist.InputSuggestion;
import com.gitplex.commons.antlr.codeassist.ParentedElement;
import com.gitplex.commons.antlr.codeassist.test.CodeAssistTest2Lexer;
import com.gitplex.commons.antlr.grammar.LexerRuleRefElementSpec;
public class TestCodeAssist2 {
private static final String[] BRANCHS = new String[]{"master", "dev", "feature1", "feature2"};
private CodeAssist codeAssist = new CodeAssist(CodeAssistTest2Lexer.class) {
private static final long serialVersionUID = 1L;
@Override
protected List<InputSuggestion> suggest(ParentedElement element, String matchWith, int count) {
if (element.getSpec() instanceof LexerRuleRefElementSpec) {
LexerRuleRefElementSpec spec = (LexerRuleRefElementSpec) element.getSpec();
if (spec.getRuleName().equals("Value")) {
return new FenceAware(codeAssist.getGrammar(), "(", ")") {
@Override
protected List<InputSuggestion> match(String matchWith, int count) {
if (element.getRoot().getLastMatchedToken().getType() == CodeAssistTest2Lexer.BRANCH) {
List<InputSuggestion> suggestions = new ArrayList<>();
for (String value: BRANCHS) {
if (value.toLowerCase().contains(matchWith.toLowerCase()))
suggestions.add(new InputSuggestion(value));
}
return suggestions;
} else {
return null;
}
}
}.suggest(element.getSpec(), matchWith, count);
}
}
return null;
}
};
private List<InputStatus> suggest(InputStatus inputStatus, String ruleName) {
List<InputStatus> suggestions = new ArrayList<>();
for (InputCompletion completion: codeAssist.suggest(inputStatus, ruleName, Integer.MAX_VALUE))
suggestions.add(completion.complete(inputStatus));
return suggestions;
}
@Test
public void test() {
List<InputStatus> suggestions;
suggestions = suggest(new InputStatus("message"), "query");
assertEquals(1, suggestions.size());
assertEquals("message(:8", suggestions.get(0).toString());
suggestions = suggest(new InputStatus("branch"), "query");
assertEquals(4, suggestions.size());
assertEquals("branch(master):14", suggestions.get(0).toString());
assertEquals("branch(dev):11", suggestions.get(1).toString());
assertEquals("branch(feature1):16", suggestions.get(2).toString());
assertEquals("branch(feature2):16", suggestions.get(3).toString());
suggestions = suggest(new InputStatus("branch(feature)"), "query");
assertEquals(12, suggestions.size());
assertEquals("branch(feature)branch(:22", suggestions.get(0).toString());
assertEquals("branch(feature)tag(:19", suggestions.get(1).toString());
assertEquals("branch(feature)id(:18", suggestions.get(2).toString());
assertEquals("branch(feature)^:16", suggestions.get(3).toString());
assertEquals("branch(feature)before(:22", suggestions.get(4).toString());
assertEquals("branch(feature)after(:21", suggestions.get(5).toString());
assertEquals("branch(feature)committer(:25", suggestions.get(6).toString());
assertEquals("branch(feature)author(:22", suggestions.get(7).toString());
assertEquals("branch(feature)path(:20", suggestions.get(8).toString());
assertEquals("branch(feature)message(:23", suggestions.get(9).toString());
assertEquals("branch(feature)..:17", suggestions.get(10).toString());
assertEquals("branch(feature)...:18", suggestions.get(11).toString());
suggestions = suggest(new InputStatus(""), "revisionCriteria");
assertEquals(4, suggestions.size());
assertEquals("^:1", suggestions.get(0).toString());
assertEquals("branch(:7", suggestions.get(1).toString());
assertEquals("tag(:4", suggestions.get(2).toString());
assertEquals("id(:3", suggestions.get(3).toString());
suggestions = suggest(new InputStatus("branch(master)"), "revisionCriteria");
assertEquals(2, suggestions.size());
assertEquals("branch(master)..:16", suggestions.get(0).toString());
assertEquals("branch(master)...:17", suggestions.get(1).toString());
suggestions = suggest(new InputStatus("br"), "query");
assertEquals(1, suggestions.size());
assertEquals("branch(:7", suggestions.get(0).toString());
suggestions = suggest(new InputStatus("branch("), "query");
assertEquals(4, suggestions.size());
assertEquals("branch(master):14", suggestions.get(0).toString());
assertEquals("branch(dev):11", suggestions.get(1).toString());
assertEquals("branch(feature1):16", suggestions.get(2).toString());
assertEquals("branch(feature2):16", suggestions.get(3).toString());
suggestions = suggest(new InputStatus("branch( fea"), "query");
assertEquals(2, suggestions.size());
assertEquals("branch(feature1):16", suggestions.get(0).toString());
assertEquals("branch(feature2):16", suggestions.get(1).toString());
suggestions = suggest(new InputStatus("tag"), "query");
assertEquals(1, suggestions.size());
assertEquals("tag(:4", suggestions.get(0).toString());
suggestions = suggest(new InputStatus("branch(master)t"), "query");
assertEquals(1, suggestions.size());
assertEquals("branch(master)tag(:18", suggestions.get(0).toString());
}
}

View File

@ -1,108 +0,0 @@
package com.gitplex.commons.antlr.codeassist;
import static org.junit.Assert.assertEquals;
import java.util.ArrayList;
import java.util.List;
import org.junit.Test;
import com.gitplex.commons.antlr.codeassist.CodeAssist;
import com.gitplex.commons.antlr.codeassist.FenceAware;
import com.gitplex.commons.antlr.codeassist.InputCompletion;
import com.gitplex.commons.antlr.codeassist.InputStatus;
import com.gitplex.commons.antlr.codeassist.InputSuggestion;
import com.gitplex.commons.antlr.codeassist.ParentedElement;
import com.gitplex.commons.antlr.codeassist.test.CodeAssistTest3Lexer;
import com.gitplex.commons.antlr.grammar.RuleRefElementSpec;
import com.gitplex.commons.antlr.parser.Element;
public class TestCodeAssist3 {
private static final String[] AUTHORS = new String[]{"robin shen", "steve luo", "justin"};
private CodeAssist codeAssist = new CodeAssist(CodeAssistTest3Lexer.class) {
private static final long serialVersionUID = 1L;
@Override
protected List<InputSuggestion> suggest(final ParentedElement element, String matchWith, int count) {
if (element.getSpec() instanceof RuleRefElementSpec) {
RuleRefElementSpec spec = (RuleRefElementSpec) element.getSpec();
if (spec.getRuleName().equals("value")) {
return new FenceAware(codeAssist.getGrammar(), "\"", "\"") {
@Override
protected List<InputSuggestion> match(String matchWith, int count) {
List<InputSuggestion> suggestions = new ArrayList<>();
Element criteriaElement = element.findParentByRule("criteria");
if (criteriaElement.getFirstMatchedToken().getText().equals("author")) {
for (String value: AUTHORS) {
if (value.toLowerCase().contains(matchWith.toLowerCase()))
suggestions.add(new InputSuggestion(value));
}
}
return suggestions;
}
}.suggest(element.getSpec(), matchWith, count);
}
}
return null;
}
};
private List<InputStatus> suggest(InputStatus inputStatus, String ruleName) {
List<InputStatus> suggestions = new ArrayList<>();
for (InputCompletion completion: codeAssist.suggest(inputStatus, ruleName, Integer.MAX_VALUE))
suggestions.add(completion.complete(inputStatus));
return suggestions;
}
@Test
public void test() {
List<InputStatus> suggestions;
suggestions = suggest(new InputStatus("title: hello author:"), "query");
assertEquals(3, suggestions.size());
assertEquals("title: hello author:\"robin shen\":32", suggestions.get(0).toString());
assertEquals("title: hello author:\"steve luo\":31", suggestions.get(1).toString());
assertEquals("title: hello author:justin:26", suggestions.get(2).toString());
suggestions = suggest(new InputStatus("title: hello world"), "query");
assertEquals(1, suggestions.size());
assertEquals("title: \"hello world\":20", suggestions.get(0).toString());
suggestions = suggest(new InputStatus(""), "query");
assertEquals(2, suggestions.size());
assertEquals("title::6", suggestions.get(0).toString());
assertEquals("author::7", suggestions.get(1).toString());
suggestions = suggest(new InputStatus("title:"), "query");
assertEquals(1, suggestions.size());
assertEquals("title:\":7", suggestions.get(0).toString());
suggestions = suggest(new InputStatus("author: dustin"), "query");
assertEquals(0, suggestions.size());
suggestions = suggest(new InputStatus("author: dustin "), "query");
assertEquals(2, suggestions.size());
assertEquals("author: dustin title::21", suggestions.get(0).toString());
assertEquals("author: dustin author::22", suggestions.get(1).toString());
suggestions = suggest(new InputStatus("author: \"robin shen\""), "query");
assertEquals(2, suggestions.size());
assertEquals("author: \"robin shen\"title::26", suggestions.get(0).toString());
assertEquals("author: \"robin shen\"author::27", suggestions.get(1).toString());
suggestions = suggest(new InputStatus("title: hello"), "query");
assertEquals(0, suggestions.size());
suggestions = suggest(new InputStatus("title: hello "), "query");
assertEquals(2, suggestions.size());
assertEquals("title: hello title::19", suggestions.get(0).toString());
assertEquals("title: hello author::20", suggestions.get(1).toString());
}
}

View File

@ -1,68 +0,0 @@
package com.gitplex.commons.antlr.codeassist;
import static org.junit.Assert.assertEquals;
import java.util.ArrayList;
import java.util.List;
import org.junit.Test;
import com.gitplex.commons.antlr.codeassist.CodeAssist;
import com.gitplex.commons.antlr.codeassist.InputCompletion;
import com.gitplex.commons.antlr.codeassist.InputStatus;
import com.gitplex.commons.antlr.codeassist.InputSuggestion;
import com.gitplex.commons.antlr.codeassist.ParentedElement;
import com.gitplex.commons.antlr.codeassist.test.CodeAssistTest4Lexer;
public class TestCodeAssist4 {
private CodeAssist codeAssist = new CodeAssist(CodeAssistTest4Lexer.class) {
private static final long serialVersionUID = 1L;
@Override
protected List<InputSuggestion> suggest(ParentedElement element, String matchWith, int count) {
return null;
}
};
private List<InputStatus> suggest(InputStatus inputStatus, String ruleName) {
List<InputStatus> suggestions = new ArrayList<>();
for (InputCompletion completion: codeAssist.suggest(inputStatus, ruleName, Integer.MAX_VALUE))
suggestions.add(completion.complete(inputStatus));
return suggestions;
}
@Test
public void test() {
List<InputStatus> suggestions;
suggestions = suggest(new InputStatus("a"), "stat");
assertEquals(6, suggestions.size());
assertEquals("a=:2", suggestions.get(0).toString());
assertEquals("a;:2", suggestions.get(1).toString());
assertEquals("a+:2", suggestions.get(2).toString());
assertEquals("a-:2", suggestions.get(3).toString());
assertEquals("a*:2", suggestions.get(4).toString());
assertEquals("a/:2", suggestions.get(5).toString());
suggestions = suggest(new InputStatus(""), "stat");
assertEquals(2, suggestions.size());
assertEquals(";:1", suggestions.get(0).toString());
assertEquals("(:1", suggestions.get(1).toString());
suggestions = suggest(new InputStatus("5*"), "stat");
assertEquals(1, suggestions.size());
assertEquals("5*(:3", suggestions.get(0).toString());
suggestions = suggest(new InputStatus("5"), "stat");
assertEquals(5, suggestions.size());
assertEquals("5;:2", suggestions.get(0).toString());
assertEquals("5+:2", suggestions.get(1).toString());
assertEquals("5-:2", suggestions.get(2).toString());
assertEquals("5*:2", suggestions.get(3).toString());
assertEquals("5/:2", suggestions.get(4).toString());
}
}

View File

@ -1,147 +0,0 @@
package com.gitplex.commons.antlr.codeassist;
import static org.junit.Assert.assertEquals;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import org.junit.Test;
import com.google.common.collect.Lists;
import com.gitplex.commons.antlr.codeassist.CodeAssist;
import com.gitplex.commons.antlr.codeassist.InputCompletion;
import com.gitplex.commons.antlr.codeassist.InputStatus;
import com.gitplex.commons.antlr.codeassist.InputSuggestion;
import com.gitplex.commons.antlr.codeassist.ParentedElement;
import com.gitplex.commons.antlr.codeassist.test.CodeAssistTest5Lexer;
import com.gitplex.commons.antlr.grammar.ElementSpec;
import com.gitplex.commons.antlr.grammar.LexerRuleRefElementSpec;
import com.gitplex.commons.antlr.grammar.RuleRefElementSpec;
import com.gitplex.commons.antlr.parser.Element;
/**
* This test case uses MySQL select grammar.
*
* @author robin
*
*/
public class TestCodeAssist5 {
private static final Map<String, List<String>> SCHEMA_TABLES = new LinkedHashMap<>();
private static final Map<String, List<String>> TABLE_COLUMNS = new LinkedHashMap<>();
private static final String DEFAULT_SCHEMA = "schemaA";
static {
SCHEMA_TABLES.put("schemaA", Lists.newArrayList("tableA", "tableB"));
SCHEMA_TABLES.put("schemaB", Lists.newArrayList("tableC", "tableD"));
TABLE_COLUMNS.put("tableA", Lists.newArrayList("columnA", "columnB"));
TABLE_COLUMNS.put("tableB", Lists.newArrayList("columnC", "columnD"));
TABLE_COLUMNS.put("tableC", Lists.newArrayList("columnE", "columnF"));
TABLE_COLUMNS.put("tableD", Lists.newArrayList("columnG", "columnH"));
}
private CodeAssist codeAssist = new CodeAssist(CodeAssistTest5Lexer.class,
new String[]{
"com/gitplex/commons/antlr/codeassist/test/CodeAssistTest5Lexer.g4",
"com/gitplex/commons/antlr/codeassist/test/CodeAssistTest5Parser.g4"},
"CodeAssistTest5Parser.tokens") {
private static final long serialVersionUID = 1L;
@Override
protected List<InputSuggestion> suggest(final ParentedElement element, String matchWith, int count) {
ElementSpec spec = element.getSpec();
if (spec instanceof RuleRefElementSpec) {
RuleRefElementSpec ruleElementSpec = (RuleRefElementSpec) spec;
if (ruleElementSpec.getRuleName().equals("schema_name")) {
List<InputSuggestion> suggestions = new ArrayList<>();
for (String schemaName: SCHEMA_TABLES.keySet()) {
if (schemaName.startsWith(matchWith))
suggestions.add(new InputSuggestion(schemaName));
}
return suggestions;
}
} else if (spec instanceof LexerRuleRefElementSpec) {
LexerRuleRefElementSpec lexerRuleRefElementSpec = (LexerRuleRefElementSpec) spec;
if ("tableName".equals(lexerRuleRefElementSpec.getLabel())) {
List<InputSuggestion> suggestions = new ArrayList<>();
Element columnNameElement = element.findParentByRule("column_name");
String schemaName;
List<Element> schemaNameElements = columnNameElement.findChildrenByRule("schema_name", true);
if (!schemaNameElements.isEmpty())
schemaName = schemaNameElements.get(0).getMatchedText();
else
schemaName = DEFAULT_SCHEMA;
if (SCHEMA_TABLES.containsKey(schemaName)) {
for (String tableName: SCHEMA_TABLES.get(schemaName)) {
if (tableName.startsWith(matchWith))
suggestions.add(new InputSuggestion(tableName));
}
}
return suggestions;
} else if ("columnName".equals(lexerRuleRefElementSpec.getLabel())) {
List<InputSuggestion> suggestions = new ArrayList<>();
Element columnNameElement = element.findParentByRule("column_name");
List<Element> tableNameElements = columnNameElement.findChildrenByLabel("tableName", true);
if (!tableNameElements.isEmpty()) {
String tableName = tableNameElements.get(0).getMatchedText();
if (TABLE_COLUMNS.containsKey(tableName)) {
for (String columnName: TABLE_COLUMNS.get(tableName)) {
if (columnName.startsWith(matchWith))
suggestions.add(new InputSuggestion(columnName));
}
}
}
return suggestions;
}
}
return null;
}
@Override
protected InputSuggestion wrapAsSuggestion(ParentedElement expectedElement, String literal, boolean complete) {
if (literal.length() > 1)
return super.wrapAsSuggestion(expectedElement, literal, complete);
else
return null;
}
};
private List<InputStatus> suggest(InputStatus inputStatus, String ruleName) {
List<InputStatus> suggestions = new ArrayList<>();
for (InputCompletion completion: codeAssist.suggest(inputStatus, ruleName, Integer.MAX_VALUE))
suggestions.add(completion.complete(inputStatus));
return suggestions;
}
@Test
public void test() {
List<InputStatus> suggestions;
suggestions = suggest(new InputStatus("select tableC."), "stat");
assertEquals(2, suggestions.size());
assertEquals("select tableC.columnE:21", suggestions.get(0).toString());
assertEquals("select tableC.columnF:21", suggestions.get(1).toString());
suggestions = suggest(new InputStatus("select schemaB."), "stat");
assertEquals(2, suggestions.size());
assertEquals("select schemaB.tableC.:22", suggestions.get(0).toString());
assertEquals("select schemaB.tableD.:22", suggestions.get(1).toString());
suggestions = suggest(new InputStatus("select schema"), "stat");
assertEquals(2, suggestions.size());
assertEquals("select schemaA.:15", suggestions.get(0).toString());
assertEquals("select schemaB.:15", suggestions.get(1).toString());
suggestions = suggest(new InputStatus("select table"), "stat");
assertEquals(2, suggestions.size());
assertEquals("select tableA.:14", suggestions.get(0).toString());
assertEquals("select tableB.:14", suggestions.get(1).toString());
}
}

View File

@ -6,7 +6,6 @@
<groupId>com.gitplex</groupId>
<artifactId>server-parent</artifactId>
<version>1.0-EAP-build26</version>
<relativePath>../parent</relativePath>
</parent>
<build>
<plugins>
@ -14,9 +13,6 @@
<groupId>com.gitplex</groupId>
<artifactId>plugin-maven</artifactId>
</plugin>
<plugin>
<artifactId>maven-archetype-plugin</artifactId>
</plugin>
<plugin>
<artifactId>maven-source-plugin</artifactId>
</plugin>
@ -30,39 +26,249 @@
</plugins>
</build>
<dependencies>
<dependency>
<groupId>com.gitplex</groupId>
<artifactId>server-wicket</artifactId>
<version>1.0-EAP-build26</version>
</dependency>
<dependency>
<groupId>com.gitplex</groupId>
<artifactId>server-schedule</artifactId>
<version>1.0-EAP-build26</version>
</dependency>
<dependency>
<groupId>com.gitplex</groupId>
<artifactId>server-git</artifactId>
<version>1.0-EAP-build26</version>
</dependency>
<dependency>
<groupId>com.gitplex</groupId>
<artifactId>server-jersey</artifactId>
<version>1.0-EAP-build26</version>
</dependency>
<dependency>
<groupId>org.jetbrains.xodus</groupId>
<artifactId>xodus-entity-store</artifactId>
</dependency>
<dependency>
<groupId>com.gitplex</groupId>
<artifactId>server-git</artifactId>
<version>1.0-EAP-build26</version>
<type>test-jar</type>
<scope>test</scope>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-core</artifactId>
<version>${shiroVersion}</version>
<exclusions>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-web</artifactId>
<version>${shiroVersion}</version>
</dependency>
<dependency>
<groupId>com.pmease.security.shiro</groupId>
<artifactId>shiro-bcrypt</artifactId>
<version>1.0.2</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-guice</artifactId>
<version>${shiroVersion}</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>${hibernateVersion}</version>
<exclusions>
<exclusion>
<groupId>dom4j</groupId>
<artifactId>dom4j</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-ehcache</artifactId>
<version>${hibernateVersion}</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>${hibernateVersion}</version>
<exclusions>
<exclusion>
<groupId>dom4j</groupId>
<artifactId>dom4j</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-hikaricp</artifactId>
<version>${hibernateVersion}</version>
<exclusions>
<exclusion>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP-java6</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
<version>2.4.5</version>
</dependency>
<dependency>
<groupId>org.glassfish</groupId>
<artifactId>javax.el</artifactId>
<version>3.0.0</version>
</dependency>
<dependency>
<groupId>org.hsqldb</groupId>
<artifactId>hsqldb</artifactId>
<version>2.3.3</version>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>9.4.1208</version>
</dependency>
<dependency>
<groupId>org.mariadb.jdbc</groupId>
<artifactId>mariadb-java-client</artifactId>
<version>1.5.2</version>
</dependency>
<dependency>
<groupId>org.dom4j</groupId>
<artifactId>dom4j</artifactId>
<version>2.0.0</version>
</dependency>
<dependency>
<groupId>com.thoughtworks.xstream</groupId>
<artifactId>xstream</artifactId>
<version>1.4.9</version>
</dependency>
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
</dependency>
<dependency>
<groupId>org.unbescape</groupId>
<artifactId>unbescape</artifactId>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
</dependency>
<dependency>
<groupId>com.gitplex</groupId>
<artifactId>launcher-bootstrap</artifactId>
<version>1.0.0</version>
</dependency>
<dependency>
<groupId>commons-httpclient</groupId>
<artifactId>commons-httpclient</artifactId>
</dependency>
<dependency>
<groupId>joda-time</groupId>
<artifactId>joda-time</artifactId>
</dependency>
<dependency>
<groupId>org.jsoup</groupId>
<artifactId>jsoup</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-email</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-collections4</artifactId>
</dependency>
<dependency>
<groupId>org.apache.ant</groupId>
<artifactId>ant</artifactId>
</dependency>
<dependency>
<groupId>org.javassist</groupId>
<artifactId>javassist</artifactId>
</dependency>
<dependency>
<groupId>com.googlecode.juniversalchardet</groupId>
<artifactId>juniversalchardet</artifactId>
<version>1.0.3</version>
</dependency>
<dependency>
<groupId>org.apache.tika</groupId>
<artifactId>tika-core</artifactId>
</dependency>
<dependency>
<groupId>com.gitplex</groupId>
<artifactId>jsymbol</artifactId>
<version>1.0.0-SNAPSHOT</version>
<exclusions>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.pegdown</groupId>
<artifactId>pegdown</artifactId>
<version>1.6.0</version>
</dependency>
<dependency>
<groupId>com.gitplex</groupId>
<artifactId>jsyntax</artifactId>
<version>1.0.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artifactId>
<exclusions>
<exclusion>
<groupId>c3p0</groupId>
<artifactId>c3p0</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-guava</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-joda</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.jaxrs</groupId>
<artifactId>jackson-jaxrs-json-provider</artifactId>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-server</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-servlets</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-servlet</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.jetty.websocket</groupId>
<artifactId>websocket-server</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.jgit</groupId>
<artifactId>org.eclipse.jgit.http.server</artifactId>
<version>${jgitVersion}</version>
</dependency>
<dependency>
<groupId>org.eclipse.jgit</groupId>
<artifactId>org.eclipse.jgit.archive</artifactId>
<version>${jgitVersion}</version>
</dependency>
</dependencies>
<properties>
<moduleClass>com.gitplex.server.core.CoreModule</moduleClass>
<moduleClass>com.gitplex.server.CoreModule</moduleClass>
<hibernateVersion>5.1.0.Final</hibernateVersion>
<shiroVersion>1.2.2</shiroVersion>
<jgitVersion>4.4.1.201607150455-r</jgitVersion>
</properties>
</project>

View File

@ -0,0 +1,510 @@
package com.gitplex.server;
import java.io.Serializable;
import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
import javax.inject.Singleton;
import javax.persistence.OneToMany;
import javax.persistence.Transient;
import javax.persistence.Version;
import javax.validation.Configuration;
import javax.validation.Validation;
import javax.validation.Validator;
import javax.validation.ValidatorFactory;
import org.apache.shiro.authc.credential.PasswordService;
import org.apache.shiro.guice.aop.ShiroAopModule;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.web.filter.mgt.FilterChainManager;
import org.apache.shiro.web.filter.mgt.FilterChainResolver;
import org.apache.shiro.web.mgt.WebSecurityManager;
import org.apache.shiro.web.servlet.ShiroFilter;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.hibernate.CallbackException;
import org.hibernate.Interceptor;
import org.hibernate.boot.model.naming.PhysicalNamingStrategy;
import org.hibernate.collection.internal.PersistentBag;
import org.hibernate.type.Type;
import org.pegdown.Parser;
import org.pegdown.plugins.ToHtmlSerializerPlugin;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.gitplex.launcher.loader.AbstractPlugin;
import com.gitplex.launcher.loader.AbstractPluginModule;
import com.gitplex.launcher.loader.ImplementationProvider;
import com.gitplex.launcher.loader.LoaderUtils;
import com.gitplex.launcher.bootstrap.Bootstrap;
import com.gitplex.launcher.bootstrap.Command;
import com.gitplex.server.command.DefaultApplyDBConstraintsCommand;
import com.gitplex.server.command.DefaultBackupCommand;
import com.gitplex.server.command.DefaultCheckDataVersionCommand;
import com.gitplex.server.command.DefaultCleanCommand;
import com.gitplex.server.command.DefaultDBDialectCommand;
import com.gitplex.server.command.DefaultRestoreCommand;
import com.gitplex.server.command.DefaultUpgradeCommand;
import com.gitplex.server.command.ResetAdminPasswordCommand;
import com.gitplex.server.entity.EntityLocator;
import com.gitplex.server.git.config.GitConfig;
import com.gitplex.server.git.config.SpecifiedGit;
import com.gitplex.server.git.config.SystemGit;
import com.gitplex.server.git.jackson.GitObjectMapperConfigurator;
import com.gitplex.server.manager.AccountManager;
import com.gitplex.server.manager.AttachmentManager;
import com.gitplex.server.manager.BatchWorkManager;
import com.gitplex.server.manager.BranchWatchManager;
import com.gitplex.server.manager.CodeCommentInfoManager;
import com.gitplex.server.manager.CodeCommentManager;
import com.gitplex.server.manager.CodeCommentRelationManager;
import com.gitplex.server.manager.CodeCommentReplyManager;
import com.gitplex.server.manager.CodeCommentStatusChangeManager;
import com.gitplex.server.manager.CommitInfoManager;
import com.gitplex.server.manager.ConfigManager;
import com.gitplex.server.manager.DataManager;
import com.gitplex.server.manager.DepotManager;
import com.gitplex.server.manager.MailManager;
import com.gitplex.server.manager.OrganizationMembershipManager;
import com.gitplex.server.manager.PullRequestCommentManager;
import com.gitplex.server.manager.PullRequestInfoManager;
import com.gitplex.server.manager.PullRequestManager;
import com.gitplex.server.manager.PullRequestReferenceManager;
import com.gitplex.server.manager.PullRequestReviewInvitationManager;
import com.gitplex.server.manager.PullRequestReviewManager;
import com.gitplex.server.manager.PullRequestStatusChangeManager;
import com.gitplex.server.manager.PullRequestTaskManager;
import com.gitplex.server.manager.PullRequestUpdateManager;
import com.gitplex.server.manager.PullRequestVerificationManager;
import com.gitplex.server.manager.PullRequestWatchManager;
import com.gitplex.server.manager.StorageManager;
import com.gitplex.server.manager.TeamAuthorizationManager;
import com.gitplex.server.manager.TeamManager;
import com.gitplex.server.manager.TeamMembershipManager;
import com.gitplex.server.manager.UserAuthorizationManager;
import com.gitplex.server.manager.VisitInfoManager;
import com.gitplex.server.manager.WorkExecutor;
import com.gitplex.server.manager.impl.DefaultAccountManager;
import com.gitplex.server.manager.impl.DefaultAttachmentManager;
import com.gitplex.server.manager.impl.DefaultBatchWorkManager;
import com.gitplex.server.manager.impl.DefaultBranchWatchManager;
import com.gitplex.server.manager.impl.DefaultCodeCommentInfoManager;
import com.gitplex.server.manager.impl.DefaultCodeCommentManager;
import com.gitplex.server.manager.impl.DefaultCodeCommentRelationManager;
import com.gitplex.server.manager.impl.DefaultCodeCommentReplyManager;
import com.gitplex.server.manager.impl.DefaultCodeCommentStatusChangeManager;
import com.gitplex.server.manager.impl.DefaultCommitInfoManager;
import com.gitplex.server.manager.impl.DefaultConfigManager;
import com.gitplex.server.manager.impl.DefaultDataManager;
import com.gitplex.server.manager.impl.DefaultDepotManager;
import com.gitplex.server.manager.impl.DefaultMailManager;
import com.gitplex.server.manager.impl.DefaultOrganizationMembershipManager;
import com.gitplex.server.manager.impl.DefaultPullRequestCommentManager;
import com.gitplex.server.manager.impl.DefaultPullRequestInfoManager;
import com.gitplex.server.manager.impl.DefaultPullRequestManager;
import com.gitplex.server.manager.impl.DefaultPullRequestReferenceManager;
import com.gitplex.server.manager.impl.DefaultPullRequestReviewInvitationManager;
import com.gitplex.server.manager.impl.DefaultPullRequestReviewManager;
import com.gitplex.server.manager.impl.DefaultPullRequestStatusChangeManager;
import com.gitplex.server.manager.impl.DefaultPullRequestTaskManager;
import com.gitplex.server.manager.impl.DefaultPullRequestUpdateManager;
import com.gitplex.server.manager.impl.DefaultPullRequestVerificationManager;
import com.gitplex.server.manager.impl.DefaultPullRequestWatchManager;
import com.gitplex.server.manager.impl.DefaultStorageManager;
import com.gitplex.server.manager.impl.DefaultTeamAuthorizationManager;
import com.gitplex.server.manager.impl.DefaultTeamManager;
import com.gitplex.server.manager.impl.DefaultTeamMembershipManager;
import com.gitplex.server.manager.impl.DefaultUserAuthorizationManager;
import com.gitplex.server.manager.impl.DefaultVisitInfoManager;
import com.gitplex.server.manager.impl.DefaultWorkExecutor;
import com.gitplex.server.migration.DatabaseMigrator;
import com.gitplex.server.migration.JpaConverter;
import com.gitplex.server.migration.Migrator;
import com.gitplex.server.migration.PersistentBagConverter;
import com.gitplex.server.migration.VersionTable;
import com.gitplex.server.persistence.AbstractEntity;
import com.gitplex.server.persistence.DefaultIdManager;
import com.gitplex.server.persistence.DefaultPersistManager;
import com.gitplex.server.persistence.DefaultUnitOfWork;
import com.gitplex.server.persistence.HibernateInterceptor;
import com.gitplex.server.persistence.IdManager;
import com.gitplex.server.persistence.ModelProvider;
import com.gitplex.server.persistence.PersistListener;
import com.gitplex.server.persistence.PersistManager;
import com.gitplex.server.persistence.PrefixedNamingStrategy;
import com.gitplex.server.persistence.SessionInterceptor;
import com.gitplex.server.persistence.TransactionInterceptor;
import com.gitplex.server.persistence.UnitOfWork;
import com.gitplex.server.persistence.annotation.Sessional;
import com.gitplex.server.persistence.annotation.Transactional;
import com.gitplex.server.persistence.dao.Dao;
import com.gitplex.server.persistence.dao.DefaultDao;
import com.gitplex.server.security.BasicAuthenticationFilter;
import com.gitplex.server.security.DefaultFilterChainResolver;
import com.gitplex.server.security.DefaultWebSecurityManager;
import com.gitplex.server.security.FilterChainConfigurator;
import com.gitplex.server.security.SecurityRealm;
import com.gitplex.server.util.ClassUtils;
import com.gitplex.server.util.jackson.ObjectMapperConfigurator;
import com.gitplex.server.util.jackson.ObjectMapperProvider;
import com.gitplex.server.util.jackson.hibernate.HibernateObjectMapperConfigurator;
import com.gitplex.server.util.jetty.DefaultJettyRunner;
import com.gitplex.server.util.jetty.JettyRunner;
import com.gitplex.server.util.markdown.DefaultMarkdownManager;
import com.gitplex.server.util.markdown.HtmlTransformer;
import com.gitplex.server.util.markdown.MarkdownExtension;
import com.gitplex.server.util.markdown.MarkdownManager;
import com.gitplex.server.util.markdown.NormalizeTransformer;
import com.gitplex.server.util.schedule.DefaultTaskScheduler;
import com.gitplex.server.util.schedule.TaskScheduler;
import com.gitplex.server.util.validation.AccountNameReservation;
import com.gitplex.server.util.validation.DefaultEntityValidator;
import com.gitplex.server.util.validation.DepotNameReservation;
import com.gitplex.server.util.validation.EntityValidator;
import com.gitplex.server.util.validation.ValidatorProvider;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import com.google.inject.matcher.AbstractMatcher;
import com.google.inject.matcher.Matchers;
import com.pmease.security.shiro.bcrypt.BCryptPasswordService;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.annotations.XStreamOmitField;
import com.thoughtworks.xstream.converters.basic.NullConverter;
import com.thoughtworks.xstream.converters.extended.ISO8601DateConverter;
import com.thoughtworks.xstream.converters.extended.ISO8601SqlTimestampConverter;
import com.thoughtworks.xstream.converters.reflection.ReflectionProvider;
import com.thoughtworks.xstream.core.JVM;
import com.thoughtworks.xstream.mapper.MapperWrapper;
/**
* NOTE: Do not forget to rename moduleClass property defined in the pom if you've renamed this class.
*
*/
public class CoreModule extends AbstractPluginModule {
@Override
protected void configure() {
super.configure();
bind(JettyRunner.class).to(DefaultJettyRunner.class);
bind(ServletContextHandler.class).toProvider(DefaultJettyRunner.class);
bind(ObjectMapper.class).toProvider(ObjectMapperProvider.class).in(Singleton.class);
bind(ValidatorFactory.class).toProvider(new com.google.inject.Provider<ValidatorFactory>() {
@Override
public ValidatorFactory get() {
Configuration<?> configuration = Validation.byDefaultProvider().configure();
return configuration.buildValidatorFactory();
}
}).in(Singleton.class);
bind(Validator.class).toProvider(ValidatorProvider.class).in(Singleton.class);
// put your guice bindings here
bind(TaskScheduler.class).to(DefaultTaskScheduler.class);
contribute(MarkdownExtension.class, new MarkdownExtension() {
@Override
public Collection<Class<? extends Parser>> getInlineParsers() {
return null;
}
@Override
public Collection<ToHtmlSerializerPlugin> getHtmlSerializers() {
return null;
}
@Override
public Collection<Class<? extends Parser>> getBlockParsers() {
return null;
}
@Override
public Collection<HtmlTransformer> getHtmlTransformers() {
return Lists.newArrayList((HtmlTransformer)new NormalizeTransformer());
}
});
bind(MarkdownManager.class).to(DefaultMarkdownManager.class);
configurePersistence();
bind(Migrator.class).to(DatabaseMigrator.class);
contribute(ModelProvider.class, new ModelProvider() {
@Override
public Collection<Class<? extends AbstractEntity>> getModelClasses() {
Collection<Class<? extends AbstractEntity>> modelClasses =
new HashSet<Class<? extends AbstractEntity>>();
modelClasses.addAll(LoaderUtils.findImplementations(AbstractEntity.class, EntityLocator.class));
return modelClasses;
}
});
/*
* Contribute empty reservations to avoid Guice complain
*/
contribute(AccountNameReservation.class, new AccountNameReservation() {
@Override
public Set<String> getReserved() {
return Sets.newHashSet();
}
});
/*
* Contribute empty reservations to avoid Guice complain
*/
contribute(DepotNameReservation.class, new DepotNameReservation() {
@Override
public Set<String> getReserved() {
return Sets.newHashSet();
}
});
contribute(ImplementationProvider.class, new ImplementationProvider() {
@Override
public Collection<Class<?>> getImplementations() {
Collection<Class<?>> implementations = new HashSet<Class<?>>();
implementations.add(SystemGit.class);
implementations.add(SpecifiedGit.class);
return implementations;
}
@Override
public Class<?> getAbstractClass() {
return GitConfig.class;
}
});
bind(GitConfig.class).toProvider(GitConfigProvider.class);
/*
* Declare bindings explicitly instead of using ImplementedBy annotation as
* HK2 to guice bridge can only search in explicit bindings in Guice
*/
bind(StorageManager.class).to(DefaultStorageManager.class);
bind(ConfigManager.class).to(DefaultConfigManager.class);
bind(DataManager.class).to(DefaultDataManager.class);
bind(PullRequestCommentManager.class).to(DefaultPullRequestCommentManager.class);
bind(CodeCommentManager.class).to(DefaultCodeCommentManager.class);
bind(PullRequestManager.class).to(DefaultPullRequestManager.class);
bind(PullRequestUpdateManager.class).to(DefaultPullRequestUpdateManager.class);
bind(DepotManager.class).to(DefaultDepotManager.class);
bind(AccountManager.class).to(DefaultAccountManager.class);
bind(PullRequestVerificationManager.class).to(DefaultPullRequestVerificationManager.class);
bind(PullRequestReviewInvitationManager.class).to(DefaultPullRequestReviewInvitationManager.class);
bind(PullRequestReviewManager.class).to(DefaultPullRequestReviewManager.class);
bind(MailManager.class).to(DefaultMailManager.class);
bind(BranchWatchManager.class).to(DefaultBranchWatchManager.class);
bind(PullRequestTaskManager.class).to(DefaultPullRequestTaskManager.class);
bind(PullRequestWatchManager.class).to(DefaultPullRequestWatchManager.class);
bind(CommitInfoManager.class).to(DefaultCommitInfoManager.class);
bind(PullRequestInfoManager.class).to(DefaultPullRequestInfoManager.class);
bind(CodeCommentInfoManager.class).to(DefaultCodeCommentInfoManager.class);
bind(VisitInfoManager.class).to(DefaultVisitInfoManager.class);
bind(BatchWorkManager.class).to(DefaultBatchWorkManager.class);
bind(TeamManager.class).to(DefaultTeamManager.class);
bind(OrganizationMembershipManager.class).to(DefaultOrganizationMembershipManager.class);
bind(TeamMembershipManager.class).to(DefaultTeamMembershipManager.class);
bind(TeamAuthorizationManager.class).to(DefaultTeamAuthorizationManager.class);
bind(UserAuthorizationManager.class).to(DefaultUserAuthorizationManager.class);
bind(PullRequestStatusChangeManager.class).to(DefaultPullRequestStatusChangeManager.class);
bind(CodeCommentReplyManager.class).to(DefaultCodeCommentReplyManager.class);
bind(AttachmentManager.class).to(DefaultAttachmentManager.class);
bind(CodeCommentRelationManager.class).to(DefaultCodeCommentRelationManager.class);
bind(CodeCommentStatusChangeManager.class).to(DefaultCodeCommentStatusChangeManager.class);
bind(PullRequestReferenceManager.class).to(DefaultPullRequestReferenceManager.class);
bind(WorkExecutor.class).to(DefaultWorkExecutor.class);
contribute(ObjectMapperConfigurator.class, GitObjectMapperConfigurator.class);
contribute(ObjectMapperConfigurator.class, HibernateObjectMapperConfigurator.class);
bind(AuthorizingRealm.class).to(SecurityRealm.class);
bind(WebSecurityManager.class).to(DefaultWebSecurityManager.class);
bind(FilterChainResolver.class).to(DefaultFilterChainResolver.class);
bind(BasicAuthenticationFilter.class);
bind(PasswordService.class).to(BCryptPasswordService.class).in(Singleton.class);
bind(ShiroFilter.class);
install(new ShiroAopModule());
contribute(FilterChainConfigurator.class, new FilterChainConfigurator() {
@Override
public void configure(FilterChainManager filterChainManager) {
filterChainManager.createChain("/**/info/refs", "noSessionCreation, authcBasic");
filterChainManager.createChain("/**/git-upload-pack", "noSessionCreation, authcBasic");
filterChainManager.createChain("/**/git-receive-pack", "noSessionCreation, authcBasic");
}
});
bind(EntityValidator.class).to(DefaultEntityValidator.class);
if (Bootstrap.command != null
&& Bootstrap.command.getName().equals("reset_admin_password")) {
bind(PersistManager.class).to(ResetAdminPasswordCommand.class);
}
}
private void configurePersistence() {
// Use an optional binding here in case our client does not like to
// start persist service provided by this plugin
bind(Interceptor.class).to(HibernateInterceptor.class);
bind(PhysicalNamingStrategy.class).toInstance(new PrefixedNamingStrategy("g_"));
bind(UnitOfWork.class).to(DefaultUnitOfWork.class);
bind(IdManager.class).to(DefaultIdManager.class);
bind(Dao.class).to(DefaultDao.class);
TransactionInterceptor transactionInterceptor = new TransactionInterceptor();
requestInjection(transactionInterceptor);
bindInterceptor(Matchers.any(), new AbstractMatcher<AnnotatedElement>() {
@Override
public boolean matches(AnnotatedElement element) {
return element.isAnnotationPresent(Transactional.class) && !((Method) element).isSynthetic();
}
}, transactionInterceptor);
SessionInterceptor sessionInterceptor = new SessionInterceptor();
requestInjection(sessionInterceptor);
bindInterceptor(Matchers.any(), new AbstractMatcher<AnnotatedElement>() {
@Override
public boolean matches(AnnotatedElement element) {
return element.isAnnotationPresent(Sessional.class) && !((Method) element).isSynthetic();
}
}, sessionInterceptor);
contribute(PersistListener.class, new PersistListener() {
@Override
public boolean onSave(Object entity, Serializable id, Object[] state, String[] propertyNames, Type[] types)
throws CallbackException {
return false;
}
@Override
public boolean onLoad(Object entity, Serializable id, Object[] state, String[] propertyNames, Type[] types)
throws CallbackException {
return false;
}
@Override
public boolean onFlushDirty(Object entity, Serializable id, Object[] currentState, Object[] previousState,
String[] propertyNames, Type[] types) throws CallbackException {
return false;
}
@Override
public void onDelete(Object entity, Serializable id, Object[] state, String[] propertyNames, Type[] types)
throws CallbackException {
}
});
contribute(ModelProvider.class, new ModelProvider() {
@SuppressWarnings("unchecked")
@Override
public Collection<Class<? extends AbstractEntity>> getModelClasses() {
return Lists.newArrayList(VersionTable.class);
}
});
// put your guice bindings here
bind(XStream.class).toProvider(new com.google.inject.Provider<XStream>() {
@SuppressWarnings("rawtypes")
@Override
public XStream get() {
ReflectionProvider reflectionProvider = JVM.newReflectionProvider();
XStream xstream = new XStream(reflectionProvider) {
@Override
protected MapperWrapper wrapMapper(MapperWrapper next) {
return new MapperWrapper(next) {
@Override
public boolean shouldSerializeMember(Class definedIn, String fieldName) {
Field field = reflectionProvider.getField(definedIn, fieldName);
return field.getAnnotation(XStreamOmitField.class) == null &&
field.getAnnotation(Transient.class) == null &&
field.getAnnotation(OneToMany.class) == null &&
field.getAnnotation(Version.class) == null;
}
@SuppressWarnings("unchecked")
@Override
public String serializedClass(Class type) {
if (type == PersistentBag.class)
return super.serializedClass(ArrayList.class);
else if (type != null)
return super.serializedClass(ClassUtils.unproxy(type));
else
return super.serializedClass(type);
}
};
}
};
// register NullConverter as highest; otherwise NPE when unmarshal a map
// containing an entry with value set to null.
xstream.registerConverter(new NullConverter(), XStream.PRIORITY_VERY_HIGH);
xstream.registerConverter(new PersistentBagConverter(xstream.getMapper()), 200);
xstream.registerConverter(new JpaConverter(xstream.getMapper(), xstream.getReflectionProvider()));
xstream.registerConverter(new ISO8601DateConverter(), 100);
xstream.registerConverter(new ISO8601SqlTimestampConverter(), 100);
xstream.autodetectAnnotations(true);
return xstream;
}
}).in(Singleton.class);
if (Bootstrap.command != null) {
if (Command.RESTORE.equals(Bootstrap.command.getName()))
bind(PersistManager.class).to(DefaultRestoreCommand.class);
else if (Command.APPLY_DB_CONSTRAINTS.equals(Bootstrap.command.getName()))
bind(PersistManager.class).to(DefaultApplyDBConstraintsCommand.class);
else if (Command.BACKUP.equals(Bootstrap.command.getName()))
bind(PersistManager.class).to(DefaultBackupCommand.class);
else if (Command.CHECK_DATA_VERSION.equals(Bootstrap.command.getName()))
bind(PersistManager.class).to(DefaultCheckDataVersionCommand.class);
else if (Command.UPGRADE.equals(Bootstrap.command.getName()))
bind(PersistManager.class).to(DefaultUpgradeCommand.class);
else if (Command.CLEAN.equals(Bootstrap.command.getName()))
bind(PersistManager.class).to(DefaultCleanCommand.class);
else if (Command.DB_DIALECT.equals(Bootstrap.command.getName()))
bind(PersistManager.class).to(DefaultDBDialectCommand.class);
else
bind(PersistManager.class).to(DefaultPersistManager.class);
} else {
bind(PersistManager.class).to(DefaultPersistManager.class);
}
}
@Override
protected Class<? extends AbstractPlugin> getPluginClass() {
return GitPlex.class;
}
}

View File

@ -1,11 +1,11 @@
package com.gitplex.server.core;
package com.gitplex.server;
import javax.inject.Inject;
import javax.inject.Provider;
import javax.inject.Singleton;
import com.gitplex.commons.git.GitConfig;
import com.gitplex.server.core.manager.ConfigManager;
import com.gitplex.server.git.config.GitConfig;
import com.gitplex.server.manager.ConfigManager;
@Singleton
public class GitConfigProvider implements Provider<GitConfig> {

View File

@ -1,4 +1,4 @@
package com.gitplex.server.core;
package com.gitplex.server;
import java.io.ObjectStreamException;
import java.io.Serializable;
@ -17,22 +17,27 @@ import org.apache.shiro.util.ThreadContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.gitplex.commons.hibernate.Sessional;
import com.gitplex.commons.hibernate.dao.Dao;
import com.gitplex.calla.loader.AbstractPlugin;
import com.gitplex.calla.loader.AppLoader;
import com.gitplex.calla.loader.ListenerRegistry;
import com.gitplex.calla.loader.ManagedSerializedForm;
import com.gitplex.commons.util.init.InitStage;
import com.gitplex.commons.util.init.ManualConfig;
import com.gitplex.server.core.event.lifecycle.SystemStarted;
import com.gitplex.server.core.event.lifecycle.SystemStarting;
import com.gitplex.server.core.event.lifecycle.SystemStopped;
import com.gitplex.server.core.event.lifecycle.SystemStopping;
import com.gitplex.server.core.manager.AccountManager;
import com.gitplex.server.core.manager.ConfigManager;
import com.gitplex.server.core.manager.DataManager;
import com.gitplex.server.core.setting.ServerConfig;
import com.gitplex.launcher.loader.AbstractPlugin;
import com.gitplex.launcher.loader.AppLoader;
import com.gitplex.launcher.loader.ListenerRegistry;
import com.gitplex.launcher.loader.ManagedSerializedForm;
import com.gitplex.launcher.bootstrap.Bootstrap;
import com.gitplex.server.event.lifecycle.SystemStarted;
import com.gitplex.server.event.lifecycle.SystemStarting;
import com.gitplex.server.event.lifecycle.SystemStopped;
import com.gitplex.server.event.lifecycle.SystemStopping;
import com.gitplex.server.manager.AccountManager;
import com.gitplex.server.manager.ConfigManager;
import com.gitplex.server.manager.DataManager;
import com.gitplex.server.persistence.PersistManager;
import com.gitplex.server.persistence.UnitOfWork;
import com.gitplex.server.persistence.annotation.Sessional;
import com.gitplex.server.persistence.dao.Dao;
import com.gitplex.server.util.init.InitStage;
import com.gitplex.server.util.init.ManualConfig;
import com.gitplex.server.util.jetty.JettyRunner;
import com.gitplex.server.util.schedule.TaskScheduler;
import com.gitplex.server.util.serverconfig.ServerConfig;
public class GitPlex extends AbstractPlugin implements Serializable {
@ -40,8 +45,16 @@ public class GitPlex extends AbstractPlugin implements Serializable {
private static final Pattern DOCLINK_PATTERN = Pattern.compile("\\d+\\.\\d+");
private final JettyRunner jettyRunner;
private final TaskScheduler taskScheduler;
private final PersistManager persistManager;
private final Dao dao;
private final UnitOfWork unitOfWork;
private final ConfigManager configManager;
private final DataManager dataManager;
@ -55,9 +68,14 @@ public class GitPlex extends AbstractPlugin implements Serializable {
private volatile InitStage initStage;
@Inject
public GitPlex(Dao dao, ServerConfig serverConfig, DataManager dataManager, ConfigManager configManager,
AccountManager accountManager, ListenerRegistry listenerRegistry) {
public GitPlex(JettyRunner jettyRunner, TaskScheduler taskScheduler, PersistManager persistManager,
Dao dao, UnitOfWork unitOfWork, ServerConfig serverConfig, DataManager dataManager,
ConfigManager configManager, AccountManager accountManager, ListenerRegistry listenerRegistry) {
this.jettyRunner = jettyRunner;
this.taskScheduler = taskScheduler;
this.persistManager = persistManager;
this.dao = dao;
this.unitOfWork = unitOfWork;
this.configManager = configManager;
this.dataManager = dataManager;
this.serverConfig = serverConfig;
@ -68,23 +86,34 @@ public class GitPlex extends AbstractPlugin implements Serializable {
}
@Override
@Sessional
public void start() {
List<ManualConfig> manualConfigs = dataManager.init();
if (!manualConfigs.isEmpty()) {
logger.warn("Please set up the server at " + guessServerUrl());
initStage = new InitStage("Server Setup", manualConfigs);
initStage.waitFor();
// clear session in order to pick up changes made in interactive setup
dao.getSession().clear();
if (Bootstrap.command == null) {
jettyRunner.start();
taskScheduler.start();
}
ThreadContext.bind(accountManager.getRoot().asSubject());
listenerRegistry.post(new SystemStarting());
persistManager.start();
unitOfWork.begin();
try {
List<ManualConfig> manualConfigs = dataManager.init();
if (!manualConfigs.isEmpty()) {
logger.warn("Please set up the server at " + guessServerUrl());
initStage = new InitStage("Server Setup", manualConfigs);
initStage.waitFor();
// clear session in order to pick up changes made in interactive setup
dao.getSession().clear();
}
ThreadContext.bind(accountManager.getRoot().asSubject());
listenerRegistry.post(new SystemStarting());
} finally {
unitOfWork.end();
}
}
@Sessional
@ -154,13 +183,21 @@ public class GitPlex extends AbstractPlugin implements Serializable {
listenerRegistry.post(new SystemStopping());
}
@Sessional
@Override
public void stop() {
listenerRegistry.post(new SystemStopped());
ThreadContext.unbindSubject();
unitOfWork.begin();
try {
listenerRegistry.post(new SystemStopped());
ThreadContext.unbindSubject();
} finally {
unitOfWork.end();
}
persistManager.stop();
taskScheduler.stop();
jettyRunner.stop();
}
public Object writeReplace() throws ObjectStreamException {
return new ManagedSerializedForm(GitPlex.class);
}

View File

@ -1,4 +1,4 @@
package com.gitplex.commons.hibernate.command;
package com.gitplex.server.command;
import java.io.BufferedReader;
import java.io.IOException;
@ -15,14 +15,14 @@ import org.hibernate.boot.model.naming.PhysicalNamingStrategy;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.gitplex.commons.hibernate.DefaultPersistManager;
import com.gitplex.commons.hibernate.EntityValidator;
import com.gitplex.commons.hibernate.HibernateProperties;
import com.gitplex.commons.hibernate.IdManager;
import com.gitplex.commons.hibernate.ModelProvider;
import com.gitplex.commons.hibernate.dao.Dao;
import com.gitplex.commons.hibernate.migration.Migrator;
import com.gitplex.calla.bootstrap.Bootstrap;
import com.gitplex.launcher.bootstrap.Bootstrap;
import com.gitplex.server.migration.Migrator;
import com.gitplex.server.persistence.DefaultPersistManager;
import com.gitplex.server.persistence.HibernateProperties;
import com.gitplex.server.persistence.IdManager;
import com.gitplex.server.persistence.ModelProvider;
import com.gitplex.server.persistence.dao.Dao;
import com.gitplex.server.util.validation.EntityValidator;
@Singleton
public class DefaultApplyDBConstraintsCommand extends DefaultPersistManager {

View File

@ -1,4 +1,4 @@
package com.gitplex.commons.hibernate.command;
package com.gitplex.server.command;
import java.io.File;
import java.util.Set;
@ -12,17 +12,17 @@ import org.hibernate.boot.model.naming.PhysicalNamingStrategy;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.gitplex.commons.hibernate.DefaultPersistManager;
import com.gitplex.commons.hibernate.EntityValidator;
import com.gitplex.commons.hibernate.HibernateProperties;
import com.gitplex.commons.hibernate.IdManager;
import com.gitplex.commons.hibernate.ModelProvider;
import com.gitplex.commons.hibernate.dao.Dao;
import com.gitplex.commons.hibernate.migration.Migrator;
import com.google.common.base.Throwables;
import com.gitplex.calla.bootstrap.Bootstrap;
import com.gitplex.calla.bootstrap.BootstrapUtils;
import com.gitplex.commons.util.FileUtils;
import com.gitplex.launcher.bootstrap.Bootstrap;
import com.gitplex.launcher.bootstrap.BootstrapUtils;
import com.gitplex.server.migration.Migrator;
import com.gitplex.server.persistence.DefaultPersistManager;
import com.gitplex.server.persistence.HibernateProperties;
import com.gitplex.server.persistence.IdManager;
import com.gitplex.server.persistence.ModelProvider;
import com.gitplex.server.persistence.dao.Dao;
import com.gitplex.server.util.FileUtils;
import com.gitplex.server.util.validation.EntityValidator;
@Singleton
public class DefaultBackupCommand extends DefaultPersistManager {

View File

@ -1,4 +1,4 @@
package com.gitplex.commons.hibernate.command;
package com.gitplex.server.command;
import java.util.Set;
@ -11,14 +11,14 @@ import org.hibernate.boot.model.naming.PhysicalNamingStrategy;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.gitplex.calla.bootstrap.Bootstrap;
import com.gitplex.commons.hibernate.DefaultPersistManager;
import com.gitplex.commons.hibernate.EntityValidator;
import com.gitplex.commons.hibernate.HibernateProperties;
import com.gitplex.commons.hibernate.IdManager;
import com.gitplex.commons.hibernate.ModelProvider;
import com.gitplex.commons.hibernate.dao.Dao;
import com.gitplex.commons.hibernate.migration.Migrator;
import com.gitplex.launcher.bootstrap.Bootstrap;
import com.gitplex.server.migration.Migrator;
import com.gitplex.server.persistence.DefaultPersistManager;
import com.gitplex.server.persistence.HibernateProperties;
import com.gitplex.server.persistence.IdManager;
import com.gitplex.server.persistence.ModelProvider;
import com.gitplex.server.persistence.dao.Dao;
import com.gitplex.server.util.validation.EntityValidator;
@Singleton
public class DefaultCheckDataVersionCommand extends DefaultPersistManager {

View File

@ -1,4 +1,4 @@
package com.gitplex.commons.hibernate.command;
package com.gitplex.server.command;
import java.util.Set;
@ -12,14 +12,14 @@ import org.hibernate.boot.model.naming.PhysicalNamingStrategy;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.gitplex.commons.hibernate.DefaultPersistManager;
import com.gitplex.commons.hibernate.EntityValidator;
import com.gitplex.commons.hibernate.HibernateProperties;
import com.gitplex.commons.hibernate.IdManager;
import com.gitplex.commons.hibernate.ModelProvider;
import com.gitplex.commons.hibernate.dao.Dao;
import com.gitplex.commons.hibernate.migration.Migrator;
import com.gitplex.calla.bootstrap.Bootstrap;
import com.gitplex.launcher.bootstrap.Bootstrap;
import com.gitplex.server.migration.Migrator;
import com.gitplex.server.persistence.DefaultPersistManager;
import com.gitplex.server.persistence.HibernateProperties;
import com.gitplex.server.persistence.IdManager;
import com.gitplex.server.persistence.ModelProvider;
import com.gitplex.server.persistence.dao.Dao;
import com.gitplex.server.util.validation.EntityValidator;
@Singleton
public class DefaultCleanCommand extends DefaultPersistManager {

View File

@ -1,4 +1,4 @@
package com.gitplex.commons.hibernate.command;
package com.gitplex.server.command;
import java.util.Set;
@ -9,13 +9,13 @@ import org.hibernate.Interceptor;
import org.hibernate.SessionFactory;
import org.hibernate.boot.model.naming.PhysicalNamingStrategy;
import com.gitplex.commons.hibernate.DefaultPersistManager;
import com.gitplex.commons.hibernate.EntityValidator;
import com.gitplex.commons.hibernate.HibernateProperties;
import com.gitplex.commons.hibernate.IdManager;
import com.gitplex.commons.hibernate.ModelProvider;
import com.gitplex.commons.hibernate.dao.Dao;
import com.gitplex.commons.hibernate.migration.Migrator;
import com.gitplex.server.migration.Migrator;
import com.gitplex.server.persistence.DefaultPersistManager;
import com.gitplex.server.persistence.HibernateProperties;
import com.gitplex.server.persistence.IdManager;
import com.gitplex.server.persistence.ModelProvider;
import com.gitplex.server.persistence.dao.Dao;
import com.gitplex.server.util.validation.EntityValidator;
@Singleton
public class DefaultDBDialectCommand extends DefaultPersistManager {

View File

@ -1,4 +1,4 @@
package com.gitplex.commons.hibernate.command;
package com.gitplex.server.command;
import java.io.File;
import java.util.Set;
@ -12,17 +12,17 @@ import org.hibernate.boot.model.naming.PhysicalNamingStrategy;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.gitplex.commons.hibernate.DefaultPersistManager;
import com.gitplex.commons.hibernate.EntityValidator;
import com.gitplex.commons.hibernate.HibernateProperties;
import com.gitplex.commons.hibernate.IdManager;
import com.gitplex.commons.hibernate.ModelProvider;
import com.gitplex.commons.hibernate.dao.Dao;
import com.gitplex.commons.hibernate.migration.Migrator;
import com.gitplex.calla.bootstrap.Bootstrap;
import com.gitplex.calla.bootstrap.BootstrapUtils;
import com.gitplex.calla.bootstrap.Command;
import com.gitplex.commons.util.FileUtils;
import com.gitplex.launcher.bootstrap.Bootstrap;
import com.gitplex.launcher.bootstrap.BootstrapUtils;
import com.gitplex.launcher.bootstrap.Command;
import com.gitplex.server.migration.Migrator;
import com.gitplex.server.persistence.DefaultPersistManager;
import com.gitplex.server.persistence.HibernateProperties;
import com.gitplex.server.persistence.IdManager;
import com.gitplex.server.persistence.ModelProvider;
import com.gitplex.server.persistence.dao.Dao;
import com.gitplex.server.util.FileUtils;
import com.gitplex.server.util.validation.EntityValidator;
@Singleton
public class DefaultRestoreCommand extends DefaultPersistManager {

View File

@ -1,4 +1,4 @@
package com.gitplex.commons.hibernate.command;
package com.gitplex.server.command;
import java.io.File;
import java.io.IOException;
@ -17,19 +17,19 @@ import org.joda.time.format.DateTimeFormat;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.gitplex.commons.hibernate.DefaultPersistManager;
import com.gitplex.commons.hibernate.EntityValidator;
import com.gitplex.commons.hibernate.HibernateProperties;
import com.gitplex.commons.hibernate.IdManager;
import com.gitplex.commons.hibernate.ModelProvider;
import com.gitplex.commons.hibernate.dao.Dao;
import com.gitplex.commons.hibernate.migration.MigrationHelper;
import com.gitplex.commons.hibernate.migration.Migrator;
import com.gitplex.calla.bootstrap.Bootstrap;
import com.gitplex.calla.loader.PluginManager;
import com.gitplex.commons.util.FileUtils;
import com.gitplex.commons.util.execution.Commandline;
import com.gitplex.commons.util.execution.LineConsumer;
import com.gitplex.launcher.loader.PluginManager;
import com.gitplex.launcher.bootstrap.Bootstrap;
import com.gitplex.server.migration.MigrationHelper;
import com.gitplex.server.migration.Migrator;
import com.gitplex.server.persistence.DefaultPersistManager;
import com.gitplex.server.persistence.HibernateProperties;
import com.gitplex.server.persistence.IdManager;
import com.gitplex.server.persistence.ModelProvider;
import com.gitplex.server.persistence.dao.Dao;
import com.gitplex.server.util.FileUtils;
import com.gitplex.server.util.execution.Commandline;
import com.gitplex.server.util.execution.LineConsumer;
import com.gitplex.server.util.validation.EntityValidator;
@Singleton
public class DefaultUpgradeCommand extends DefaultPersistManager {
@ -51,7 +51,7 @@ public class DefaultUpgradeCommand extends DefaultPersistManager {
protected Commandline buildCommandline(File upgradeDir, String command, String...commandArgs) {
Commandline cmdline= new Commandline(System.getProperty("java.home") + "/bin/java");
cmdline.addArgs("-Xmx" + Runtime.getRuntime().maxMemory()/1024/1024 + "m", "-classpath", "*",
"com.gitplex.calla.bootstrap.Bootstrap", command);
"com.gitplex.launcher.bootstrap.Bootstrap", command);
cmdline.addArgs(commandArgs);
cmdline.workingDir(new File(upgradeDir, "boot"));
return cmdline;

View File

@ -1,4 +1,4 @@
package com.gitplex.server.core;
package com.gitplex.server.command;
import java.util.Set;
@ -12,16 +12,16 @@ import org.hibernate.boot.model.naming.PhysicalNamingStrategy;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.gitplex.calla.bootstrap.Bootstrap;
import com.gitplex.commons.hibernate.DefaultPersistManager;
import com.gitplex.commons.hibernate.EntityValidator;
import com.gitplex.commons.hibernate.HibernateProperties;
import com.gitplex.commons.hibernate.IdManager;
import com.gitplex.commons.hibernate.ModelProvider;
import com.gitplex.commons.hibernate.dao.Dao;
import com.gitplex.commons.hibernate.migration.Migrator;
import com.gitplex.server.core.entity.Account;
import com.gitplex.server.core.manager.AccountManager;
import com.gitplex.launcher.bootstrap.Bootstrap;
import com.gitplex.server.entity.Account;
import com.gitplex.server.manager.AccountManager;
import com.gitplex.server.migration.Migrator;
import com.gitplex.server.persistence.DefaultPersistManager;
import com.gitplex.server.persistence.HibernateProperties;
import com.gitplex.server.persistence.IdManager;
import com.gitplex.server.persistence.ModelProvider;
import com.gitplex.server.persistence.dao.Dao;
import com.gitplex.server.util.validation.EntityValidator;
@Singleton
public class ResetAdminPasswordCommand extends DefaultPersistManager {

View File

@ -1,42 +0,0 @@
package com.gitplex.server.core;
import java.util.Set;
import javax.inject.Inject;
import javax.inject.Singleton;
import javax.validation.ConstraintViolation;
import javax.validation.Validator;
import com.gitplex.commons.hibernate.AbstractEntity;
import com.gitplex.commons.hibernate.DefaultEntityValidator;
import com.gitplex.server.core.entity.Account;
@Singleton
public class CoreEntityValidator extends DefaultEntityValidator {
@Inject
public CoreEntityValidator(Validator validator) {
super(validator);
}
@Override
public void validate(AbstractEntity entity) {
if (entity instanceof Account) {
Account account = (Account) entity;
Set<String> excludeProperties;
if (account.isOrganization()) {
excludeProperties = Account.getOrganizationExcludeProperties();
} else {
excludeProperties = Account.getUserExcludeProperties();
}
for (ConstraintViolation<?> violation: validator.validate(account)) {
if (!excludeProperties.contains(violation.getPropertyPath().toString())) {
reportError(account, violation);
}
}
} else {
super.validate(entity);
}
}
}

View File

@ -1,223 +0,0 @@
package com.gitplex.server.core;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
import org.hibernate.boot.model.naming.PhysicalNamingStrategy;
import com.gitplex.calla.bootstrap.Bootstrap;
import com.gitplex.calla.loader.AbstractPlugin;
import com.gitplex.calla.loader.AbstractPluginModule;
import com.gitplex.calla.loader.ImplementationProvider;
import com.gitplex.calla.loader.LoaderUtils;
import com.gitplex.commons.git.GitConfig;
import com.gitplex.commons.hibernate.AbstractEntity;
import com.gitplex.commons.hibernate.EntityValidator;
import com.gitplex.commons.hibernate.ModelProvider;
import com.gitplex.commons.hibernate.PersistManager;
import com.gitplex.commons.hibernate.PrefixedNamingStrategy;
import com.gitplex.commons.hibernate.migration.Migrator;
import com.gitplex.commons.jetty.ServletConfigurator;
import com.gitplex.commons.shiro.AbstractRealm;
import com.gitplex.server.core.commitmessagetransform.CommitMessageTransformer;
import com.gitplex.server.core.commitmessagetransform.PatternCommitMessageTransformer;
import com.gitplex.server.core.entity.EntityLocator;
import com.gitplex.server.core.manager.AccountManager;
import com.gitplex.server.core.manager.AttachmentManager;
import com.gitplex.server.core.manager.BatchWorkManager;
import com.gitplex.server.core.manager.BranchWatchManager;
import com.gitplex.server.core.manager.CodeCommentInfoManager;
import com.gitplex.server.core.manager.CodeCommentManager;
import com.gitplex.server.core.manager.CodeCommentRelationManager;
import com.gitplex.server.core.manager.CodeCommentReplyManager;
import com.gitplex.server.core.manager.CodeCommentStatusChangeManager;
import com.gitplex.server.core.manager.CommitInfoManager;
import com.gitplex.server.core.manager.ConfigManager;
import com.gitplex.server.core.manager.DataManager;
import com.gitplex.server.core.manager.DepotManager;
import com.gitplex.server.core.manager.MailManager;
import com.gitplex.server.core.manager.OrganizationMembershipManager;
import com.gitplex.server.core.manager.PullRequestCommentManager;
import com.gitplex.server.core.manager.PullRequestInfoManager;
import com.gitplex.server.core.manager.PullRequestManager;
import com.gitplex.server.core.manager.PullRequestReferenceManager;
import com.gitplex.server.core.manager.PullRequestReviewInvitationManager;
import com.gitplex.server.core.manager.PullRequestReviewManager;
import com.gitplex.server.core.manager.PullRequestStatusChangeManager;
import com.gitplex.server.core.manager.PullRequestTaskManager;
import com.gitplex.server.core.manager.PullRequestUpdateManager;
import com.gitplex.server.core.manager.PullRequestVerificationManager;
import com.gitplex.server.core.manager.PullRequestWatchManager;
import com.gitplex.server.core.manager.StorageManager;
import com.gitplex.server.core.manager.TeamAuthorizationManager;
import com.gitplex.server.core.manager.TeamManager;
import com.gitplex.server.core.manager.TeamMembershipManager;
import com.gitplex.server.core.manager.UserAuthorizationManager;
import com.gitplex.server.core.manager.VisitInfoManager;
import com.gitplex.server.core.manager.WorkExecutor;
import com.gitplex.server.core.manager.impl.DefaultAccountManager;
import com.gitplex.server.core.manager.impl.DefaultAttachmentManager;
import com.gitplex.server.core.manager.impl.DefaultBatchWorkManager;
import com.gitplex.server.core.manager.impl.DefaultBranchWatchManager;
import com.gitplex.server.core.manager.impl.DefaultCodeCommentInfoManager;
import com.gitplex.server.core.manager.impl.DefaultCodeCommentManager;
import com.gitplex.server.core.manager.impl.DefaultCodeCommentRelationManager;
import com.gitplex.server.core.manager.impl.DefaultCodeCommentReplyManager;
import com.gitplex.server.core.manager.impl.DefaultCodeCommentStatusChangeManager;
import com.gitplex.server.core.manager.impl.DefaultCommitInfoManager;
import com.gitplex.server.core.manager.impl.DefaultConfigManager;
import com.gitplex.server.core.manager.impl.DefaultDataManager;
import com.gitplex.server.core.manager.impl.DefaultDepotManager;
import com.gitplex.server.core.manager.impl.DefaultMailManager;
import com.gitplex.server.core.manager.impl.DefaultOrganizationMembershipManager;
import com.gitplex.server.core.manager.impl.DefaultPullRequestCommentManager;
import com.gitplex.server.core.manager.impl.DefaultPullRequestInfoManager;
import com.gitplex.server.core.manager.impl.DefaultPullRequestManager;
import com.gitplex.server.core.manager.impl.DefaultPullRequestReferenceManager;
import com.gitplex.server.core.manager.impl.DefaultPullRequestReviewInvitationManager;
import com.gitplex.server.core.manager.impl.DefaultPullRequestReviewManager;
import com.gitplex.server.core.manager.impl.DefaultPullRequestStatusChangeManager;
import com.gitplex.server.core.manager.impl.DefaultPullRequestTaskManager;
import com.gitplex.server.core.manager.impl.DefaultPullRequestUpdateManager;
import com.gitplex.server.core.manager.impl.DefaultPullRequestVerificationManager;
import com.gitplex.server.core.manager.impl.DefaultPullRequestWatchManager;
import com.gitplex.server.core.manager.impl.DefaultStorageManager;
import com.gitplex.server.core.manager.impl.DefaultTeamAuthorizationManager;
import com.gitplex.server.core.manager.impl.DefaultTeamManager;
import com.gitplex.server.core.manager.impl.DefaultTeamMembershipManager;
import com.gitplex.server.core.manager.impl.DefaultUserAuthorizationManager;
import com.gitplex.server.core.manager.impl.DefaultVisitInfoManager;
import com.gitplex.server.core.manager.impl.DefaultWorkExecutor;
import com.gitplex.server.core.migration.DatabaseMigrator;
import com.gitplex.server.core.security.SecurityRealm;
import com.gitplex.server.core.setting.SpecifiedGit;
import com.gitplex.server.core.setting.SystemGit;
import com.gitplex.server.core.util.validation.AccountNameReservation;
import com.gitplex.server.core.util.validation.DepotNameReservation;
import com.google.common.collect.Sets;
/**
* NOTE: Do not forget to rename moduleClass property defined in the pom if you've renamed this class.
*
*/
public class CoreModule extends AbstractPluginModule {
@Override
protected void configure() {
super.configure();
bind(Migrator.class).to(DatabaseMigrator.class);
bind(PhysicalNamingStrategy.class).toInstance(new PrefixedNamingStrategy("g_"));
contribute(ModelProvider.class, new ModelProvider() {
@Override
public Collection<Class<? extends AbstractEntity>> getModelClasses() {
Collection<Class<? extends AbstractEntity>> modelClasses =
new HashSet<Class<? extends AbstractEntity>>();
modelClasses.addAll(LoaderUtils.findImplementations(AbstractEntity.class, EntityLocator.class));
return modelClasses;
}
});
/*
* Contribute empty reservations to avoid Guice complain
*/
contribute(AccountNameReservation.class, new AccountNameReservation() {
@Override
public Set<String> getReserved() {
return Sets.newHashSet();
}
});
/*
* Contribute empty reservations to avoid Guice complain
*/
contribute(DepotNameReservation.class, new DepotNameReservation() {
@Override
public Set<String> getReserved() {
return Sets.newHashSet();
}
});
contribute(ServletConfigurator.class, CoreServletConfigurator.class);
contribute(ImplementationProvider.class, new ImplementationProvider() {
@Override
public Collection<Class<?>> getImplementations() {
Collection<Class<?>> implementations = new HashSet<Class<?>>();
implementations.add(SystemGit.class);
implementations.add(SpecifiedGit.class);
return implementations;
}
@Override
public Class<?> getAbstractClass() {
return GitConfig.class;
}
});
contribute(CommitMessageTransformer.class, PatternCommitMessageTransformer.class);
bind(GitConfig.class).toProvider(GitConfigProvider.class);
/*
* Declare bindings explicitly instead of using ImplementedBy annotation as
* HK2 to guice bridge can only search in explicit bindings in Guice
*/
bind(StorageManager.class).to(DefaultStorageManager.class);
bind(ConfigManager.class).to(DefaultConfigManager.class);
bind(DataManager.class).to(DefaultDataManager.class);
bind(PullRequestCommentManager.class).to(DefaultPullRequestCommentManager.class);
bind(CodeCommentManager.class).to(DefaultCodeCommentManager.class);
bind(PullRequestManager.class).to(DefaultPullRequestManager.class);
bind(PullRequestUpdateManager.class).to(DefaultPullRequestUpdateManager.class);
bind(DepotManager.class).to(DefaultDepotManager.class);
bind(AccountManager.class).to(DefaultAccountManager.class);
bind(PullRequestVerificationManager.class).to(DefaultPullRequestVerificationManager.class);
bind(PullRequestReviewInvitationManager.class).to(DefaultPullRequestReviewInvitationManager.class);
bind(PullRequestReviewManager.class).to(DefaultPullRequestReviewManager.class);
bind(MailManager.class).to(DefaultMailManager.class);
bind(BranchWatchManager.class).to(DefaultBranchWatchManager.class);
bind(PullRequestTaskManager.class).to(DefaultPullRequestTaskManager.class);
bind(PullRequestWatchManager.class).to(DefaultPullRequestWatchManager.class);
bind(CommitInfoManager.class).to(DefaultCommitInfoManager.class);
bind(PullRequestInfoManager.class).to(DefaultPullRequestInfoManager.class);
bind(CodeCommentInfoManager.class).to(DefaultCodeCommentInfoManager.class);
bind(VisitInfoManager.class).to(DefaultVisitInfoManager.class);
bind(BatchWorkManager.class).to(DefaultBatchWorkManager.class);
bind(TeamManager.class).to(DefaultTeamManager.class);
bind(OrganizationMembershipManager.class).to(DefaultOrganizationMembershipManager.class);
bind(TeamMembershipManager.class).to(DefaultTeamMembershipManager.class);
bind(TeamAuthorizationManager.class).to(DefaultTeamAuthorizationManager.class);
bind(UserAuthorizationManager.class).to(DefaultUserAuthorizationManager.class);
bind(PullRequestStatusChangeManager.class).to(DefaultPullRequestStatusChangeManager.class);
bind(CodeCommentReplyManager.class).to(DefaultCodeCommentReplyManager.class);
bind(AttachmentManager.class).to(DefaultAttachmentManager.class);
bind(CodeCommentRelationManager.class).to(DefaultCodeCommentRelationManager.class);
bind(CodeCommentStatusChangeManager.class).to(DefaultCodeCommentStatusChangeManager.class);
bind(PullRequestReferenceManager.class).to(DefaultPullRequestReferenceManager.class);
bind(WorkExecutor.class).to(DefaultWorkExecutor.class);
bind(AbstractRealm.class).to(SecurityRealm.class);
bind(EntityValidator.class).to(CoreEntityValidator.class);
if (Bootstrap.command != null
&& Bootstrap.command.getName().equals("reset_admin_password")) {
bind(PersistManager.class).to(ResetAdminPasswordCommand.class);
}
}
@Override
protected Class<? extends AbstractPlugin> getPluginClass() {
return GitPlex.class;
}
}

View File

@ -1,35 +0,0 @@
package com.gitplex.server.core;
import javax.inject.Inject;
import javax.inject.Singleton;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import com.gitplex.commons.jetty.ServletConfigurator;
import com.gitplex.server.core.hookcallback.GitPostReceiveCallback;
import com.gitplex.server.core.hookcallback.GitPreReceiveCallback;
@Singleton
public class CoreServletConfigurator implements ServletConfigurator {
private final GitPreReceiveCallback preReceiveServlet;
private final GitPostReceiveCallback postReceiveServlet;
@Inject
public CoreServletConfigurator(GitPreReceiveCallback preReceiveServlet, GitPostReceiveCallback postReceiveServlet) {
this.preReceiveServlet = preReceiveServlet;
this.postReceiveServlet = postReceiveServlet;
}
@Override
public void configure(ServletContextHandler context) {
ServletHolder servletHolder = new ServletHolder(preReceiveServlet);
context.addServlet(servletHolder, GitPreReceiveCallback.PATH + "/*");
servletHolder = new ServletHolder(postReceiveServlet);
context.addServlet(servletHolder, GitPostReceiveCallback.PATH + "/*");
}
}

View File

@ -1,11 +0,0 @@
package com.gitplex.server.core.commitmessagetransform;
import com.gitplex.calla.loader.ExtensionPoint;
import com.gitplex.server.core.entity.Depot;
@ExtensionPoint
public interface CommitMessageTransformer {
String transform(Depot depot, String commitMessage);
}

View File

@ -1,5 +0,0 @@
package com.gitplex.server.core.entity;
public class EntityLocator {
}

View File

@ -1,5 +0,0 @@
package com.gitplex.server.core.event.lifecycle;
public class SystemStarted {
}

View File

@ -1,5 +0,0 @@
package com.gitplex.server.core.event.lifecycle;
public class SystemStarting {
}

View File

@ -1,5 +0,0 @@
package com.gitplex.server.core.event.lifecycle;
public class SystemStopped {
}

View File

@ -1,5 +0,0 @@
package com.gitplex.server.core.event.lifecycle;
public class SystemStopping {
}

View File

@ -1,10 +0,0 @@
package com.gitplex.server.core.manager;
import com.gitplex.commons.util.concurrent.Prioritized;
import com.gitplex.server.core.manager.support.BatchWorker;
public interface BatchWorkManager {
void submit(BatchWorker worker, Prioritized work);
}

View File

@ -1,16 +0,0 @@
package com.gitplex.server.core.manager;
import java.util.Collection;
import com.gitplex.commons.hibernate.dao.EntityManager;
import com.gitplex.server.core.entity.Account;
import com.gitplex.server.core.entity.BranchWatch;
import com.gitplex.server.core.entity.Depot;
public interface BranchWatchManager extends EntityManager<BranchWatch> {
Collection<BranchWatch> find(Account user, Depot depot);
Collection<BranchWatch> find(Depot depot, String branch);
}

View File

@ -1,10 +0,0 @@
package com.gitplex.server.core.manager;
import com.gitplex.commons.hibernate.dao.EntityManager;
import com.gitplex.server.core.entity.CodeCommentReply;
public interface CodeCommentReplyManager extends EntityManager<CodeCommentReply> {
void save(CodeCommentReply reply, boolean callListeners);
}

View File

@ -1,8 +0,0 @@
package com.gitplex.server.core.manager;
import com.gitplex.commons.hibernate.dao.EntityManager;
import com.gitplex.server.core.entity.CodeCommentStatusChange;
public interface CodeCommentStatusChangeManager extends EntityManager<CodeCommentStatusChange> {
}

View File

@ -1,8 +0,0 @@
package com.gitplex.server.core.manager;
import com.gitplex.commons.hibernate.dao.EntityManager;
import com.gitplex.server.core.entity.PullRequestReference;
public interface PullRequestReferenceManager extends EntityManager<PullRequestReference> {
}

View File

@ -1,8 +0,0 @@
package com.gitplex.server.core.manager;
import com.gitplex.commons.hibernate.dao.EntityManager;
import com.gitplex.server.core.entity.PullRequestStatusChange;
public interface PullRequestStatusChangeManager extends EntityManager<PullRequestStatusChange> {
}

View File

@ -1,8 +0,0 @@
package com.gitplex.server.core.manager;
import com.gitplex.commons.hibernate.dao.EntityManager;
import com.gitplex.server.core.entity.PullRequestTask;
public interface PullRequestTaskManager extends EntityManager<PullRequestTask> {
}

View File

@ -1,8 +0,0 @@
package com.gitplex.server.core.manager;
import com.gitplex.commons.hibernate.dao.EntityManager;
import com.gitplex.server.core.entity.PullRequestWatch;
public interface PullRequestWatchManager extends EntityManager<PullRequestWatch> {
}

View File

@ -1,7 +0,0 @@
package com.gitplex.server.core.security.protectedobject;
import com.gitplex.server.core.entity.Account;
public interface AccountBelonging extends ProtectedObject {
Account getAccount();
}

View File

@ -1,4 +1,4 @@
package com.gitplex.server.core.entity;
package com.gitplex.server.entity;
import java.util.ArrayList;
import java.util.Collection;
@ -17,27 +17,34 @@ import javax.persistence.Table;
import javax.persistence.Version;
import javax.validation.constraints.NotNull;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.SimplePrincipalCollection;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.web.mgt.WebSecurityManager;
import org.eclipse.jgit.lib.PersonIdent;
import org.hibernate.annotations.Cache;
import org.hibernate.annotations.CacheConcurrencyStrategy;
import org.hibernate.validator.constraints.Email;
import org.hibernate.validator.constraints.NotEmpty;
import com.gitplex.commons.hibernate.AbstractEntity;
import com.gitplex.commons.shiro.AbstractUser;
import com.gitplex.commons.util.StringUtils;
import com.gitplex.commons.wicket.editable.annotation.Editable;
import com.gitplex.commons.wicket.editable.annotation.ExcludeValues;
import com.gitplex.commons.wicket.editable.annotation.Password;
import com.gitplex.server.core.GitPlex;
import com.gitplex.server.core.manager.TeamAuthorizationManager;
import com.gitplex.server.core.manager.TeamMembershipManager;
import com.gitplex.server.core.manager.UserAuthorizationManager;
import com.gitplex.server.core.security.privilege.DepotPrivilege;
import com.gitplex.server.core.security.protectedobject.AccountBelonging;
import com.gitplex.server.core.security.protectedobject.ProtectedObject;
import com.gitplex.server.core.util.validation.AccountName;
import com.gitplex.launcher.loader.AppLoader;
import com.gitplex.server.GitPlex;
import com.gitplex.server.manager.TeamAuthorizationManager;
import com.gitplex.server.manager.TeamMembershipManager;
import com.gitplex.server.manager.UserAuthorizationManager;
import com.gitplex.server.persistence.AbstractEntity;
import com.gitplex.server.security.privilege.DepotPrivilege;
import com.gitplex.server.security.protectedobject.AccountBelonging;
import com.gitplex.server.security.protectedobject.ProtectedObject;
import com.gitplex.server.util.StringUtils;
import com.gitplex.server.util.editable.annotation.Editable;
import com.gitplex.server.util.editable.annotation.ExcludeValues;
import com.gitplex.server.util.editable.annotation.Password;
import com.gitplex.server.util.validation.annotation.AccountName;
import com.google.common.base.Objects;
import com.google.common.base.Preconditions;
import com.google.common.collect.Sets;
@Entity
@ -46,13 +53,19 @@ import com.google.common.collect.Sets;
@Index(columnList="noSpaceName"), @Index(columnList="noSpaceFullName")})
@Cache(usage=CacheConcurrencyStrategy.READ_WRITE)
@Editable
public class Account extends AbstractUser implements ProtectedObject {
public class Account extends AbstractEntity implements AuthenticationInfo, ProtectedObject {
private static final long serialVersionUID = 1L;
public static final Long ADMINISTRATOR_ID = 1L;
private boolean organization;
@Column(unique=true, nullable=false)
private String name;
@Column(length=1024)
private String password;
private boolean organization;
private String fullName;
@ -145,17 +158,44 @@ public class Account extends AbstractUser implements ProtectedObject {
private transient Map<Account, OrganizationMembership> organizationMembersMap;
@Override
public PrincipalCollection getPrincipals() {
return new SimplePrincipalCollection(getId(), "");
}
@Override
public Object getCredentials() {
return password;
}
public Subject asSubject() {
return asSubject(getId());
}
public static Long getCurrentId() {
Object principal = SecurityUtils.getSubject().getPrincipal();
Preconditions.checkNotNull(principal);
return (Long) principal;
}
public static PrincipalCollection asPrincipal(Long userId) {
return new SimplePrincipalCollection(userId, "");
}
public static Subject asSubject(Long userId) {
WebSecurityManager securityManager = AppLoader.getInstance(WebSecurityManager.class);
return new Subject.Builder(securityManager).principals(asPrincipal(userId)).buildSubject();
}
@Editable(name="Account Name", order=100)
@AccountName
@NotEmpty
@Override
public String getName() {
return super.getName();
return name;
}
@Override
public void setName(String name) {
super.setName(name);
this.name = name;
noSpaceName = StringUtils.deleteWhitespace(name);
}
@ -163,9 +203,23 @@ public class Account extends AbstractUser implements ProtectedObject {
@Password(confirmative=true)
@NotEmpty
public String getPassword() {
return super.getPassword();
return password;
}
/**
* Set password of this user.
*
* @param password
* password to set
*/
public void setPassword(String password) {
if (password != null) {
this.password = password;
} else {
this.password = null;
}
}
@Editable(order=200)
public String getFullName() {
return fullName;

View File

@ -1,4 +1,4 @@
package com.gitplex.server.core.entity;
package com.gitplex.server.entity;
import javax.persistence.Column;
import javax.persistence.Entity;
@ -9,7 +9,7 @@ import javax.persistence.ManyToOne;
import javax.persistence.Table;
import javax.persistence.UniqueConstraint;
import com.gitplex.commons.hibernate.AbstractEntity;
import com.gitplex.server.persistence.AbstractEntity;
@Entity
@Table(

View File

@ -1,4 +1,4 @@
package com.gitplex.server.core.entity;
package com.gitplex.server.entity;
import java.io.Serializable;
import java.util.ArrayList;
@ -23,16 +23,16 @@ import javax.persistence.Version;
import org.hibernate.annotations.DynamicUpdate;
import com.gitplex.commons.hibernate.AbstractEntity;
import com.gitplex.commons.wicket.editable.EditableUtils;
import com.gitplex.server.core.GitPlex;
import com.gitplex.server.core.entity.support.CodeCommentActivity;
import com.gitplex.server.core.entity.support.CommentPos;
import com.gitplex.server.core.entity.support.CompareContext;
import com.gitplex.server.core.entity.support.LastEvent;
import com.gitplex.server.core.event.codecomment.CodeCommentEvent;
import com.gitplex.server.core.manager.VisitInfoManager;
import com.gitplex.server.core.security.SecurityUtils;
import com.gitplex.server.GitPlex;
import com.gitplex.server.entity.support.CodeCommentActivity;
import com.gitplex.server.entity.support.CommentPos;
import com.gitplex.server.entity.support.CompareContext;
import com.gitplex.server.entity.support.LastEvent;
import com.gitplex.server.event.codecomment.CodeCommentEvent;
import com.gitplex.server.manager.VisitInfoManager;
import com.gitplex.server.persistence.AbstractEntity;
import com.gitplex.server.security.SecurityUtils;
import com.gitplex.server.util.editable.EditableUtils;
/*
* @DynamicUpdate annotation here along with various @OptimisticLock annotations

View File

@ -1,4 +1,4 @@
package com.gitplex.server.core.entity;
package com.gitplex.server.entity;
import javax.persistence.Entity;
import javax.persistence.FetchType;
@ -11,7 +11,7 @@ import javax.persistence.UniqueConstraint;
import org.hibernate.annotations.Fetch;
import org.hibernate.annotations.FetchMode;
import com.gitplex.commons.hibernate.AbstractEntity;
import com.gitplex.server.persistence.AbstractEntity;
@Table(
indexes={@Index(columnList="g_request_id"), @Index(columnList="g_comment_id")},

View File

@ -1,4 +1,4 @@
package com.gitplex.server.core.entity;
package com.gitplex.server.entity;
import javax.persistence.Column;
import javax.persistence.Entity;
@ -8,7 +8,7 @@ import javax.persistence.Table;
import org.hibernate.annotations.DynamicUpdate;
import com.gitplex.server.core.entity.support.CodeCommentActivity;
import com.gitplex.server.entity.support.CodeCommentActivity;
/*
* @DynamicUpdate annotation here along with various @OptimisticLock annotations

View File

@ -1,4 +1,4 @@
package com.gitplex.server.core.entity;
package com.gitplex.server.entity;
import javax.persistence.Entity;
import javax.persistence.Index;
@ -6,7 +6,7 @@ import javax.persistence.Table;
import org.hibernate.annotations.DynamicUpdate;
import com.gitplex.server.core.entity.support.CodeCommentActivity;
import com.gitplex.server.entity.support.CodeCommentActivity;
@Entity
@Table(indexes={@Index(columnList="g_comment_id"), @Index(columnList="g_user_id")})

View File

@ -1,4 +1,4 @@
package com.gitplex.server.core.entity;
package com.gitplex.server.entity;
import java.io.Serializable;
@ -9,7 +9,7 @@ import javax.persistence.Lob;
import org.hibernate.annotations.Cache;
import org.hibernate.annotations.CacheConcurrencyStrategy;
import com.gitplex.commons.hibernate.AbstractEntity;
import com.gitplex.server.persistence.AbstractEntity;
/**
* This entity stores object in serialized form, with one entity

View File

@ -1,4 +1,4 @@
package com.gitplex.server.core.entity;
package com.gitplex.server.entity;
import java.io.File;
import java.io.IOException;
@ -64,37 +64,37 @@ import org.hibernate.annotations.CacheConcurrencyStrategy;
import org.hibernate.annotations.DynamicUpdate;
import org.hibernate.validator.constraints.NotEmpty;
import com.gitplex.calla.loader.AppLoader;
import com.gitplex.calla.loader.ListenerRegistry;
import com.gitplex.calla.loader.LoaderUtils;
import com.gitplex.commons.git.Blob;
import com.gitplex.commons.git.BlobIdent;
import com.gitplex.commons.git.GitUtils;
import com.gitplex.commons.git.RefInfo;
import com.gitplex.commons.git.Submodule;
import com.gitplex.commons.git.exception.GitObjectNotFoundException;
import com.gitplex.commons.git.exception.NotGitFileException;
import com.gitplex.commons.hibernate.AbstractEntity;
import com.gitplex.commons.hibernate.UnitOfWork;
import com.gitplex.commons.util.FileUtils;
import com.gitplex.commons.util.LockUtils;
import com.gitplex.commons.util.StringUtils;
import com.gitplex.commons.wicket.editable.annotation.Editable;
import com.gitplex.commons.wicket.editable.annotation.Markdown;
import com.gitplex.server.core.GitPlex;
import com.gitplex.server.core.entity.support.CommitMessageTransformSetting;
import com.gitplex.server.core.entity.support.IntegrationPolicy;
import com.gitplex.server.core.event.RefUpdated;
import com.gitplex.server.core.gatekeeper.AndGateKeeper;
import com.gitplex.server.core.gatekeeper.GateKeeper;
import com.gitplex.server.core.manager.ConfigManager;
import com.gitplex.server.core.manager.DepotManager;
import com.gitplex.server.core.manager.StorageManager;
import com.gitplex.server.core.manager.VisitInfoManager;
import com.gitplex.server.core.security.SecurityUtils;
import com.gitplex.server.core.security.protectedobject.AccountBelonging;
import com.gitplex.server.core.security.protectedobject.ProtectedObject;
import com.gitplex.server.core.util.validation.DepotName;
import com.gitplex.launcher.loader.AppLoader;
import com.gitplex.launcher.loader.ListenerRegistry;
import com.gitplex.launcher.loader.LoaderUtils;
import com.gitplex.server.GitPlex;
import com.gitplex.server.entity.support.CommitMessageTransformSetting;
import com.gitplex.server.entity.support.IntegrationPolicy;
import com.gitplex.server.event.RefUpdated;
import com.gitplex.server.gatekeeper.AndGateKeeper;
import com.gitplex.server.gatekeeper.GateKeeper;
import com.gitplex.server.git.Blob;
import com.gitplex.server.git.BlobIdent;
import com.gitplex.server.git.GitUtils;
import com.gitplex.server.git.RefInfo;
import com.gitplex.server.git.Submodule;
import com.gitplex.server.git.exception.GitObjectNotFoundException;
import com.gitplex.server.git.exception.NotGitFileException;
import com.gitplex.server.manager.ConfigManager;
import com.gitplex.server.manager.DepotManager;
import com.gitplex.server.manager.StorageManager;
import com.gitplex.server.manager.VisitInfoManager;
import com.gitplex.server.persistence.AbstractEntity;
import com.gitplex.server.persistence.UnitOfWork;
import com.gitplex.server.security.SecurityUtils;
import com.gitplex.server.security.protectedobject.AccountBelonging;
import com.gitplex.server.security.protectedobject.ProtectedObject;
import com.gitplex.server.util.FileUtils;
import com.gitplex.server.util.LockUtils;
import com.gitplex.server.util.StringUtils;
import com.gitplex.server.util.editable.annotation.Editable;
import com.gitplex.server.util.editable.annotation.Markdown;
import com.gitplex.server.util.validation.annotation.DepotName;
import com.google.common.base.Objects;
import com.google.common.base.Optional;
import com.google.common.base.Preconditions;

View File

@ -0,0 +1,5 @@
package com.gitplex.server.entity;
public class EntityLocator {
}

View File

@ -1,4 +1,4 @@
package com.gitplex.server.core.entity;
package com.gitplex.server.entity;
import javax.persistence.Entity;
import javax.persistence.FetchType;
@ -8,7 +8,7 @@ import javax.persistence.ManyToOne;
import javax.persistence.Table;
import javax.persistence.UniqueConstraint;
import com.gitplex.commons.hibernate.AbstractEntity;
import com.gitplex.server.persistence.AbstractEntity;
@Entity
@Table(

View File

@ -1,4 +1,4 @@
package com.gitplex.server.core.entity;
package com.gitplex.server.entity;
import java.io.IOException;
import java.io.Serializable;
@ -38,31 +38,31 @@ import org.hibernate.criterion.Criterion;
import org.hibernate.criterion.Restrictions;
import com.fasterxml.jackson.annotation.JsonView;
import com.gitplex.server.GitPlex;
import com.gitplex.server.entity.support.CloseInfo;
import com.gitplex.server.entity.support.CompareContext;
import com.gitplex.server.entity.support.DepotAndBranch;
import com.gitplex.server.entity.support.IntegrationPreview;
import com.gitplex.server.entity.support.LastEvent;
import com.gitplex.server.event.pullrequest.PullRequestCodeCommentEvent;
import com.gitplex.server.gatekeeper.checkresult.Failed;
import com.gitplex.server.gatekeeper.checkresult.GateCheckResult;
import com.gitplex.server.gatekeeper.checkresult.Pending;
import com.gitplex.server.git.GitUtils;
import com.gitplex.server.git.exception.GitObjectNotFoundException;
import com.gitplex.server.manager.CodeCommentRelationManager;
import com.gitplex.server.manager.PullRequestManager;
import com.gitplex.server.manager.PullRequestReviewManager;
import com.gitplex.server.manager.VisitInfoManager;
import com.gitplex.server.persistence.AbstractEntity;
import com.gitplex.server.persistence.UnitOfWork;
import com.gitplex.server.persistence.dao.Dao;
import com.gitplex.server.security.ObjectPermission;
import com.gitplex.server.security.SecurityUtils;
import com.gitplex.server.util.diff.WhitespaceOption;
import com.gitplex.server.util.editable.EditableUtils;
import com.gitplex.server.util.jackson.ExternalView;
import com.google.common.base.Preconditions;
import com.gitplex.commons.git.GitUtils;
import com.gitplex.commons.git.exception.GitObjectNotFoundException;
import com.gitplex.commons.hibernate.AbstractEntity;
import com.gitplex.commons.hibernate.UnitOfWork;
import com.gitplex.commons.hibernate.dao.Dao;
import com.gitplex.commons.jackson.ExternalView;
import com.gitplex.commons.util.diff.WhitespaceOption;
import com.gitplex.commons.wicket.editable.EditableUtils;
import com.gitplex.server.core.GitPlex;
import com.gitplex.server.core.entity.support.CloseInfo;
import com.gitplex.server.core.entity.support.CompareContext;
import com.gitplex.server.core.entity.support.DepotAndBranch;
import com.gitplex.server.core.entity.support.IntegrationPreview;
import com.gitplex.server.core.entity.support.LastEvent;
import com.gitplex.server.core.event.pullrequest.PullRequestCodeCommentEvent;
import com.gitplex.server.core.gatekeeper.checkresult.Failed;
import com.gitplex.server.core.gatekeeper.checkresult.GateCheckResult;
import com.gitplex.server.core.gatekeeper.checkresult.Pending;
import com.gitplex.server.core.manager.CodeCommentRelationManager;
import com.gitplex.server.core.manager.PullRequestManager;
import com.gitplex.server.core.manager.PullRequestReviewManager;
import com.gitplex.server.core.manager.VisitInfoManager;
import com.gitplex.server.core.security.ObjectPermission;
import com.gitplex.server.core.security.SecurityUtils;
@Entity
/*

View File

@ -1,4 +1,4 @@
package com.gitplex.server.core.entity;
package com.gitplex.server.entity;
import java.util.Date;
@ -15,7 +15,7 @@ import javax.persistence.Version;
import org.hibernate.annotations.DynamicUpdate;
import com.gitplex.commons.hibernate.AbstractEntity;
import com.gitplex.server.persistence.AbstractEntity;
/*
* @DynamicUpdate annotation here along with various @OptimisticLock annotations

View File

@ -1,4 +1,4 @@
package com.gitplex.server.core.entity;
package com.gitplex.server.entity;
import java.util.Date;
@ -14,7 +14,7 @@ import javax.persistence.UniqueConstraint;
import org.hibernate.annotations.Fetch;
import org.hibernate.annotations.FetchMode;
import com.gitplex.commons.hibernate.AbstractEntity;
import com.gitplex.server.persistence.AbstractEntity;
@Table(
indexes={@Index(columnList="g_referenced_id"), @Index(columnList="g_referencedBy_id"), @Index(columnList="g_user_id")},

View File

@ -1,4 +1,4 @@
package com.gitplex.server.core.entity;
package com.gitplex.server.entity;
import java.util.Date;
@ -11,7 +11,7 @@ import javax.persistence.ManyToOne;
import javax.persistence.Table;
import javax.persistence.UniqueConstraint;
import com.gitplex.commons.hibernate.AbstractEntity;
import com.gitplex.server.persistence.AbstractEntity;
@Entity
@Table(

View File

@ -1,4 +1,4 @@
package com.gitplex.server.core.entity;
package com.gitplex.server.entity;
import java.util.Date;
@ -11,7 +11,7 @@ import javax.persistence.ManyToOne;
import javax.persistence.Table;
import javax.persistence.UniqueConstraint;
import com.gitplex.commons.hibernate.AbstractEntity;
import com.gitplex.server.persistence.AbstractEntity;
@Entity
@Table(

View File

@ -1,4 +1,4 @@
package com.gitplex.server.core.entity;
package com.gitplex.server.entity;
import java.util.Date;
@ -14,7 +14,7 @@ import javax.persistence.Version;
import org.hibernate.annotations.DynamicUpdate;
import com.gitplex.commons.hibernate.AbstractEntity;
import com.gitplex.server.persistence.AbstractEntity;
@Entity
@Table(indexes={@Index(columnList="g_request_id"), @Index(columnList="g_user_id")})

View File

@ -1,4 +1,4 @@
package com.gitplex.server.core.entity;
package com.gitplex.server.entity;
import java.util.Date;
@ -11,7 +11,7 @@ import javax.persistence.ManyToOne;
import javax.persistence.Table;
import javax.persistence.UniqueConstraint;
import com.gitplex.commons.hibernate.AbstractEntity;
import com.gitplex.server.persistence.AbstractEntity;
@Entity
@Table(

View File

@ -1,4 +1,4 @@
package com.gitplex.server.core.entity;
package com.gitplex.server.entity;
import java.io.IOException;
import java.util.ArrayList;
@ -31,10 +31,10 @@ import org.eclipse.jgit.treewalk.TreeWalk;
import org.eclipse.jgit.treewalk.filter.TreeFilter;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.gitplex.server.git.GitUtils;
import com.gitplex.server.manager.impl.DefaultCodeCommentRelationManager;
import com.gitplex.server.persistence.AbstractEntity;
import com.google.common.base.Preconditions;
import com.gitplex.commons.git.GitUtils;
import com.gitplex.commons.hibernate.AbstractEntity;
import com.gitplex.server.core.manager.impl.DefaultCodeCommentRelationManager;
@Entity
@Table(indexes={@Index(columnList="g_request_id"), @Index(columnList="uuid"), @Index(columnList="date")})

View File

@ -1,4 +1,4 @@
package com.gitplex.server.core.entity;
package com.gitplex.server.entity;
import java.util.Date;
@ -11,7 +11,7 @@ import javax.persistence.ManyToOne;
import javax.persistence.Table;
import javax.persistence.UniqueConstraint;
import com.gitplex.commons.hibernate.AbstractEntity;
import com.gitplex.server.persistence.AbstractEntity;
@Entity
@Table(

View File

@ -1,4 +1,4 @@
package com.gitplex.server.core.entity;
package com.gitplex.server.entity;
import javax.annotation.Nullable;
import javax.persistence.Entity;
@ -9,7 +9,7 @@ import javax.persistence.ManyToOne;
import javax.persistence.Table;
import javax.persistence.UniqueConstraint;
import com.gitplex.commons.hibernate.AbstractEntity;
import com.gitplex.server.persistence.AbstractEntity;
@Entity
@Table(

View File

@ -1,4 +1,4 @@
package com.gitplex.server.core.entity;
package com.gitplex.server.entity;
import java.util.ArrayList;
import java.util.Collection;
@ -20,10 +20,10 @@ import org.hibernate.annotations.Cache;
import org.hibernate.annotations.CacheConcurrencyStrategy;
import org.hibernate.validator.constraints.NotEmpty;
import com.gitplex.commons.hibernate.AbstractEntity;
import com.gitplex.commons.wicket.editable.annotation.Editable;
import com.gitplex.commons.wicket.editable.annotation.Markdown;
import com.gitplex.server.core.util.validation.DepotName;
import com.gitplex.server.persistence.AbstractEntity;
import com.gitplex.server.util.editable.annotation.Editable;
import com.gitplex.server.util.editable.annotation.Markdown;
import com.gitplex.server.util.validation.annotation.DepotName;
@Entity
@Table(

Some files were not shown because too many files have changed in this diff Show More