mirror of
https://github.com/theonedev/onedev.git
synced 2025-12-08 18:26:30 +00:00
Reorganize GitPlex server projects
This commit is contained in:
parent
295436c249
commit
b8ca356829
@ -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>
|
||||
@ -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* ;
|
||||
|
||||
@ -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
|
||||
;
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -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 : '~' ;
|
||||
@ -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'
|
||||
;
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
@ -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
|
||||
}
|
||||
|
||||
}
|
||||
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
@ -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);
|
||||
}
|
||||
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,7 +0,0 @@
|
||||
package com.gitplex.commons.antlr.codeassist;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface Suggester {
|
||||
List<InputSuggestion> suggest(String matchWith);
|
||||
}
|
||||
@ -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;
|
||||
@ -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;
|
||||
@ -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;
|
||||
@ -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;
|
||||
@ -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 )+
|
||||
;
|
||||
@ -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
|
||||
;
|
||||
File diff suppressed because it is too large
Load Diff
@ -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, " ");
|
||||
}
|
||||
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
@ -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();
|
||||
}
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
@ -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, " | ");
|
||||
}
|
||||
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
@ -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>
|
||||
@ -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>
|
||||
@ -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
|
||||
}
|
||||
|
||||
}
|
||||
@ -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\");"
|
||||
+ " }"
|
||||
+ "}"));
|
||||
}
|
||||
|
||||
}
|
||||
@ -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());
|
||||
}
|
||||
|
||||
}
|
||||
@ -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());
|
||||
}
|
||||
|
||||
}
|
||||
@ -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());
|
||||
}
|
||||
|
||||
}
|
||||
@ -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());
|
||||
}
|
||||
|
||||
}
|
||||
@ -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());
|
||||
}
|
||||
|
||||
}
|
||||
268
core/pom.xml
268
core/pom.xml
@ -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>
|
||||
510
core/src/main/java/com/gitplex/server/CoreModule.java
Normal file
510
core/src/main/java/com/gitplex/server/CoreModule.java
Normal 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;
|
||||
}
|
||||
|
||||
}
|
||||
@ -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> {
|
||||
@ -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);
|
||||
}
|
||||
@ -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 {
|
||||
@ -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 {
|
||||
@ -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 {
|
||||
@ -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 {
|
||||
@ -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 {
|
||||
@ -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 {
|
||||
@ -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;
|
||||
@ -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 {
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
@ -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 + "/*");
|
||||
}
|
||||
|
||||
}
|
||||
@ -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);
|
||||
|
||||
}
|
||||
@ -1,5 +0,0 @@
|
||||
package com.gitplex.server.core.entity;
|
||||
|
||||
public class EntityLocator {
|
||||
|
||||
}
|
||||
@ -1,5 +0,0 @@
|
||||
package com.gitplex.server.core.event.lifecycle;
|
||||
|
||||
public class SystemStarted {
|
||||
|
||||
}
|
||||
@ -1,5 +0,0 @@
|
||||
package com.gitplex.server.core.event.lifecycle;
|
||||
|
||||
public class SystemStarting {
|
||||
|
||||
}
|
||||
@ -1,5 +0,0 @@
|
||||
package com.gitplex.server.core.event.lifecycle;
|
||||
|
||||
public class SystemStopped {
|
||||
|
||||
}
|
||||
@ -1,5 +0,0 @@
|
||||
package com.gitplex.server.core.event.lifecycle;
|
||||
|
||||
public class SystemStopping {
|
||||
|
||||
}
|
||||
@ -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);
|
||||
|
||||
}
|
||||
@ -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);
|
||||
|
||||
}
|
||||
@ -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);
|
||||
|
||||
}
|
||||
@ -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> {
|
||||
|
||||
}
|
||||
@ -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> {
|
||||
|
||||
}
|
||||
@ -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> {
|
||||
|
||||
}
|
||||
@ -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> {
|
||||
|
||||
}
|
||||
@ -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> {
|
||||
|
||||
}
|
||||
@ -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();
|
||||
}
|
||||
@ -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;
|
||||
@ -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(
|
||||
@ -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
|
||||
@ -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")},
|
||||
@ -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
|
||||
@ -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")})
|
||||
@ -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
|
||||
@ -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;
|
||||
@ -0,0 +1,5 @@
|
||||
package com.gitplex.server.entity;
|
||||
|
||||
public class EntityLocator {
|
||||
|
||||
}
|
||||
@ -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(
|
||||
@ -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
|
||||
/*
|
||||
@ -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
|
||||
@ -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")},
|
||||
@ -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(
|
||||
@ -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(
|
||||
@ -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")})
|
||||
@ -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(
|
||||
@ -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")})
|
||||
@ -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(
|
||||
@ -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(
|
||||
@ -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
Loading…
x
Reference in New Issue
Block a user