astNodes = new ArrayList<>();
+
+ JavaPropertiesLexer lexer = new JavaPropertiesLexer(new ANTLRInputStream(text.toCharArray(), text.length()));
+ CommonTokenStream tokens = new CommonTokenStream(lexer);
+ JavaPropertiesParser parser = new JavaPropertiesParser(tokens);
+
+ // Add listener to collect various parser errors
+ parser.addErrorListener(new ANTLRErrorListener() {
+
+ @Override
+ public void syntaxError(Recognizer, ?> recognizer, Object offendingSymbol, int line,
+ int charPositionInLine, String msg, RecognitionException e) {
+ syntaxErrors.add(createProblem(msg, ProblemCodes.PROPERTIES_SYNTAX_ERROR, (Token) offendingSymbol));
+ }
+
+ @Override
+ public void reportAmbiguity(org.antlr.v4.runtime.Parser recognizer, DFA dfa, int startIndex, int stopIndex,
+ boolean exact, BitSet ambigAlts, ATNConfigSet configs) {
+ problems.add(createProblem("Ambiguity detected!", ProblemCodes.PROPERTIES_AMBIGUITY_ERROR, recognizer.getCurrentToken()));
+ }
+
+ @Override
+ public void reportAttemptingFullContext(org.antlr.v4.runtime.Parser recognizer, DFA dfa, int startIndex,
+ int stopIndex, BitSet conflictingAlts, ATNConfigSet configs) {
+ problems.add(createProblem("Full-Context attempt detected!", ProblemCodes.PROPERTIES_FULL_CONTEXT_ERROR, recognizer.getCurrentToken()));
+ }
+
+ @Override
+ public void reportContextSensitivity(org.antlr.v4.runtime.Parser recognizer, DFA dfa, int startIndex,
+ int stopIndex, int prediction, ATNConfigSet configs) {
+ problems.add(createProblem("Context sensitivity detected!", ProblemCodes.PROPERTIES_CONTEXT_SENSITIVITY_ERROR, recognizer.getCurrentToken()));
+ }
+
+ });
+
+ // Add listener to the parse tree to collect AST nodes
+ parser.addParseListener(new JavaPropertiesBaseListener() {
+
+ private Key key = null;
+ private Value value = null;
+
+ @Override
+ public void exitPropertyLine(PropertyLineContext ctx) {
+ astNodes.add(new KeyValuePair(ctx, key, value));
+ key = null;
+ value = null;
+ }
+
+ @Override
+ public void exitCommentLine(CommentLineContext ctx) {
+ astNodes.add(new Comment(ctx));
+ }
+
+ @Override
+ public void exitKey(KeyContext ctx) {
+ key = new Key(ctx);
+ }
+
+ @Override
+ public void exitSeparatorAndValue(SeparatorAndValueContext ctx) {
+ value = new Value(ctx);
+ }
+
+ });
+
+ parser.parse();
+
+ // Collect and return parse results
+ return new ParseResults(new PropertiesAst(ImmutableList.copyOf(astNodes)), ImmutableList.copyOf(syntaxErrors), ImmutableList.copyOf(problems));
+ }
+
+ private static Problem createProblem(String message, String code, Token token) {
+ return new Problem() {
+
+ @Override
+ public String getMessage() {
+ return message;
+ }
+
+ @Override
+ public String getCode() {
+ return code;
+ }
+
+ @Override
+ public int getOffset() {
+ return token.getStartIndex();
+ }
+
+ @Override
+ public int getLength() {
+ return token.getStopIndex() - token.getStartIndex();
+ }
+
+ };
+ }
+
+ private static abstract class Node implements PropertiesAst.Node {
+
+ abstract protected ParserRuleContext getContext();
+
+ @Override
+ public int getOffset() {
+ return getContext().getStart().getStartIndex();
+ }
+
+ @Override
+ public int getLength() {
+ return getContext().getStop().getStartIndex() - getOffset() + 1;
+ }
+
+ }
+
+ private static class Comment implements PropertiesAst.Comment {
+
+ private CommentLineContext context;
+
+ public Comment(CommentLineContext context) {
+ this.context = context;
+ }
+
+ @Override
+ public int getOffset() {
+ return context.Comment().getSymbol().getStartIndex();
+ }
+
+ @Override
+ public int getLength() {
+ return context.Comment().getSymbol().getStopIndex() - getOffset() + 1;
+ }
+
+ }
+
+ private static class KeyValuePair extends Node implements PropertiesAst.KeyValuePair {
+
+ private PropertyLineContext context;
+ private Key key;
+ private Value value;
+
+ public KeyValuePair(PropertyLineContext context, Key key, Value value) {
+ this.context = context;
+ this.key = key;
+ this.value = value;
+ }
+
+ protected PropertyLineContext getContext() {
+ return context;
+ }
+
+ @Override
+ public Key getKey() {
+ return key;
+ }
+
+ @Override
+ public Value getValue() {
+ return value;
+ }
+ }
+
+ private static class Key extends Node implements PropertiesAst.Key {
+
+ private KeyContext context;
+
+ public Key(KeyContext context) {
+ this.context = context;
+ }
+
+ protected KeyContext getContext() {
+ return context;
+ }
+
+ @Override
+ public String decode() {
+ return context.getText().replace("\\:", ":").replace("\\=", "=");
+ }
+
+ }
+
+ private static class Value extends Node implements PropertiesAst.Value {
+
+ private SeparatorAndValueContext context;
+ private String value;
+ private String decoded;
+
+ public Value(SeparatorAndValueContext context) {
+ this.context = context;
+ init();
+ }
+
+ private void init() {
+ // Remove the separator, if it exists
+ value = context.getText().replaceAll("^\\s*[:=]?\\s*", "");
+ // Remove all escaped line breaks with trailing spaces
+ decoded = value.replaceAll("\\\\(\r?\n|\r)[ \t\f]*", "");
+ }
+
+ @Override
+ protected SeparatorAndValueContext getContext() {
+ return context;
+ }
+
+ @Override
+ public String decode() {
+ return decoded;
+ }
+
+ @Override
+ public int getOffset() {
+ // Offset by 1 to skip the separator
+ return context.getStart().getStartIndex() + (context.getText().length() - value.length());
+ }
+
+ }
+
+}
diff --git a/vscode-extensions/commons/java-properties/src/main/java/org/springframework/ide/vscode/properties/antlr/parser/JavaProperties.tokens b/vscode-extensions/commons/java-properties/src/main/java/org/springframework/ide/vscode/properties/antlr/parser/JavaProperties.tokens
new file mode 100644
index 000000000..fe8593417
--- /dev/null
+++ b/vscode-extensions/commons/java-properties/src/main/java/org/springframework/ide/vscode/properties/antlr/parser/JavaProperties.tokens
@@ -0,0 +1,10 @@
+Backslash=1
+Colon=2
+Equals=3
+Comment=4
+LineBreak=5
+Space=6
+IdentifierChar=7
+'\\'=1
+':'=2
+'='=3
diff --git a/vscode-extensions/commons/java-properties/src/main/java/org/springframework/ide/vscode/properties/antlr/parser/JavaPropertiesBaseListener.java b/vscode-extensions/commons/java-properties/src/main/java/org/springframework/ide/vscode/properties/antlr/parser/JavaPropertiesBaseListener.java
new file mode 100644
index 000000000..d859c9f2f
--- /dev/null
+++ b/vscode-extensions/commons/java-properties/src/main/java/org/springframework/ide/vscode/properties/antlr/parser/JavaPropertiesBaseListener.java
@@ -0,0 +1,159 @@
+// Generated from JavaProperties.g4 by ANTLR 4.5.3
+package org.springframework.ide.vscode.properties.antlr.parser;
+
+import org.antlr.v4.runtime.ParserRuleContext;
+import org.antlr.v4.runtime.tree.ErrorNode;
+import org.antlr.v4.runtime.tree.TerminalNode;
+
+/**
+ * This class provides an empty implementation of {@link JavaPropertiesListener},
+ * which can be extended to create a listener which only needs to handle a subset
+ * of the available methods.
+ */
+public class JavaPropertiesBaseListener implements JavaPropertiesListener {
+ /**
+ * {@inheritDoc}
+ *
+ * The default implementation does nothing.
+ */
+ @Override public void enterParse(JavaPropertiesParser.ParseContext ctx) { }
+ /**
+ * {@inheritDoc}
+ *
+ * The default implementation does nothing.
+ */
+ @Override public void exitParse(JavaPropertiesParser.ParseContext ctx) { }
+ /**
+ * {@inheritDoc}
+ *
+ * The default implementation does nothing.
+ */
+ @Override public void enterLine(JavaPropertiesParser.LineContext ctx) { }
+ /**
+ * {@inheritDoc}
+ *
+ * The default implementation does nothing.
+ */
+ @Override public void exitLine(JavaPropertiesParser.LineContext ctx) { }
+ /**
+ * {@inheritDoc}
+ *
+ * The default implementation does nothing.
+ */
+ @Override public void enterPropertyLine(JavaPropertiesParser.PropertyLineContext ctx) { }
+ /**
+ * {@inheritDoc}
+ *
+ * The default implementation does nothing.
+ */
+ @Override public void exitPropertyLine(JavaPropertiesParser.PropertyLineContext ctx) { }
+ /**
+ * {@inheritDoc}
+ *
+ * The default implementation does nothing.
+ */
+ @Override public void enterCommentLine(JavaPropertiesParser.CommentLineContext ctx) { }
+ /**
+ * {@inheritDoc}
+ *
+ * The default implementation does nothing.
+ */
+ @Override public void exitCommentLine(JavaPropertiesParser.CommentLineContext ctx) { }
+ /**
+ * {@inheritDoc}
+ *
+ * The default implementation does nothing.
+ */
+ @Override public void enterEmptyLine(JavaPropertiesParser.EmptyLineContext ctx) { }
+ /**
+ * {@inheritDoc}
+ *
+ * The default implementation does nothing.
+ */
+ @Override public void exitEmptyLine(JavaPropertiesParser.EmptyLineContext ctx) { }
+ /**
+ * {@inheritDoc}
+ *
+ * The default implementation does nothing.
+ */
+ @Override public void enterKeyValuePair(JavaPropertiesParser.KeyValuePairContext ctx) { }
+ /**
+ * {@inheritDoc}
+ *
+ * The default implementation does nothing.
+ */
+ @Override public void exitKeyValuePair(JavaPropertiesParser.KeyValuePairContext ctx) { }
+ /**
+ * {@inheritDoc}
+ *
+ * The default implementation does nothing.
+ */
+ @Override public void enterKey(JavaPropertiesParser.KeyContext ctx) { }
+ /**
+ * {@inheritDoc}
+ *
+ * The default implementation does nothing.
+ */
+ @Override public void exitKey(JavaPropertiesParser.KeyContext ctx) { }
+ /**
+ * {@inheritDoc}
+ *
+ * The default implementation does nothing.
+ */
+ @Override public void enterKeyChar(JavaPropertiesParser.KeyCharContext ctx) { }
+ /**
+ * {@inheritDoc}
+ *
+ * The default implementation does nothing.
+ */
+ @Override public void exitKeyChar(JavaPropertiesParser.KeyCharContext ctx) { }
+ /**
+ * {@inheritDoc}
+ *
+ * The default implementation does nothing.
+ */
+ @Override public void enterSeparatorAndValue(JavaPropertiesParser.SeparatorAndValueContext ctx) { }
+ /**
+ * {@inheritDoc}
+ *
+ * The default implementation does nothing.
+ */
+ @Override public void exitSeparatorAndValue(JavaPropertiesParser.SeparatorAndValueContext ctx) { }
+ /**
+ * {@inheritDoc}
+ *
+ * The default implementation does nothing.
+ */
+ @Override public void enterValueChar(JavaPropertiesParser.ValueCharContext ctx) { }
+ /**
+ * {@inheritDoc}
+ *
+ * The default implementation does nothing.
+ */
+ @Override public void exitValueChar(JavaPropertiesParser.ValueCharContext ctx) { }
+
+ /**
+ * {@inheritDoc}
+ *
+ * The default implementation does nothing.
+ */
+ @Override public void enterEveryRule(ParserRuleContext ctx) { }
+ /**
+ * {@inheritDoc}
+ *
+ * The default implementation does nothing.
+ */
+ @Override public void exitEveryRule(ParserRuleContext ctx) { }
+ /**
+ * {@inheritDoc}
+ *
+ * The default implementation does nothing.
+ */
+ @Override public void visitTerminal(TerminalNode node) { }
+ /**
+ * {@inheritDoc}
+ *
+ * The default implementation does nothing.
+ */
+ @Override public void visitErrorNode(ErrorNode node) { }
+}
\ No newline at end of file
diff --git a/vscode-extensions/commons/java-properties/src/main/java/org/springframework/ide/vscode/properties/antlr/parser/JavaPropertiesLexer.java b/vscode-extensions/commons/java-properties/src/main/java/org/springframework/ide/vscode/properties/antlr/parser/JavaPropertiesLexer.java
new file mode 100644
index 000000000..cac94e6bb
--- /dev/null
+++ b/vscode-extensions/commons/java-properties/src/main/java/org/springframework/ide/vscode/properties/antlr/parser/JavaPropertiesLexer.java
@@ -0,0 +1,112 @@
+// Generated from JavaProperties.g4 by ANTLR 4.5.3
+package org.springframework.ide.vscode.properties.antlr.parser;
+import org.antlr.v4.runtime.Lexer;
+import org.antlr.v4.runtime.CharStream;
+import org.antlr.v4.runtime.Token;
+import org.antlr.v4.runtime.TokenStream;
+import org.antlr.v4.runtime.*;
+import org.antlr.v4.runtime.atn.*;
+import org.antlr.v4.runtime.dfa.DFA;
+import org.antlr.v4.runtime.misc.*;
+
+@SuppressWarnings({"all", "warnings", "unchecked", "unused", "cast"})
+public class JavaPropertiesLexer extends Lexer {
+ static { RuntimeMetaData.checkVersion("4.5.3", RuntimeMetaData.VERSION); }
+
+ protected static final DFA[] _decisionToDFA;
+ protected static final PredictionContextCache _sharedContextCache =
+ new PredictionContextCache();
+ public static final int
+ Backslash=1, Colon=2, Equals=3, Comment=4, LineBreak=5, Space=6, IdentifierChar=7;
+ public static String[] modeNames = {
+ "DEFAULT_MODE"
+ };
+
+ public static final String[] ruleNames = {
+ "Backslash", "Colon", "Equals", "Comment", "LineBreak", "Space", "IdentifierChar"
+ };
+
+ private static final String[] _LITERAL_NAMES = {
+ null, "'\\'", "':'", "'='"
+ };
+ private static final String[] _SYMBOLIC_NAMES = {
+ null, "Backslash", "Colon", "Equals", "Comment", "LineBreak", "Space",
+ "IdentifierChar"
+ };
+ public static final Vocabulary VOCABULARY = new VocabularyImpl(_LITERAL_NAMES, _SYMBOLIC_NAMES);
+
+ /**
+ * @deprecated Use {@link #VOCABULARY} instead.
+ */
+ @Deprecated
+ public static final String[] tokenNames;
+ static {
+ tokenNames = new String[_SYMBOLIC_NAMES.length];
+ for (int i = 0; i < tokenNames.length; i++) {
+ tokenNames[i] = VOCABULARY.getLiteralName(i);
+ if (tokenNames[i] == null) {
+ tokenNames[i] = VOCABULARY.getSymbolicName(i);
+ }
+
+ if (tokenNames[i] == null) {
+ tokenNames[i] = "";
+ }
+ }
+ }
+
+ @Override
+ @Deprecated
+ public String[] getTokenNames() {
+ return tokenNames;
+ }
+
+ @Override
+
+ public Vocabulary getVocabulary() {
+ return VOCABULARY;
+ }
+
+
+ public JavaPropertiesLexer(CharStream input) {
+ super(input);
+ _interp = new LexerATNSimulator(this,_ATN,_decisionToDFA,_sharedContextCache);
+ }
+
+ @Override
+ public String getGrammarFileName() { return "JavaProperties.g4"; }
+
+ @Override
+ public String[] getRuleNames() { return ruleNames; }
+
+ @Override
+ public String getSerializedATN() { return _serializedATN; }
+
+ @Override
+ public String[] getModeNames() { return modeNames; }
+
+ @Override
+ public ATN getATN() { return _ATN; }
+
+ public static final String _serializedATN =
+ "\3\u0430\ud6d1\u8206\uad2d\u4417\uaef1\u8d80\uaadd\2\t)\b\1\4\2\t\2\4"+
+ "\3\t\3\4\4\t\4\4\5\t\5\4\6\t\6\4\7\t\7\4\b\t\b\3\2\3\2\3\3\3\3\3\4\3\4"+
+ "\3\5\3\5\7\5\32\n\5\f\5\16\5\35\13\5\3\6\5\6 \n\6\3\6\3\6\5\6$\n\6\3\7"+
+ "\3\7\3\b\3\b\2\2\t\3\3\5\4\7\5\t\6\13\7\r\b\17\t\3\2\6\4\2##%%\4\2\f\f"+
+ "\17\17\5\2\13\13\16\16\"\"\n\2\f\f\17\17\"\")+<?AA^^+\2\3\3\2\2\2\2"+
+ "\5\3\2\2\2\2\7\3\2\2\2\2\t\3\2\2\2\2\13\3\2\2\2\2\r\3\2\2\2\2\17\3\2\2"+
+ "\2\3\21\3\2\2\2\5\23\3\2\2\2\7\25\3\2\2\2\t\27\3\2\2\2\13#\3\2\2\2\r%"+
+ "\3\2\2\2\17\'\3\2\2\2\21\22\7^\2\2\22\4\3\2\2\2\23\24\7<\2\2\24\6\3\2"+
+ "\2\2\25\26\7?\2\2\26\b\3\2\2\2\27\33\t\2\2\2\30\32\n\3\2\2\31\30\3\2\2"+
+ "\2\32\35\3\2\2\2\33\31\3\2\2\2\33\34\3\2\2\2\34\n\3\2\2\2\35\33\3\2\2"+
+ "\2\36 \7\17\2\2\37\36\3\2\2\2\37 \3\2\2\2 !\3\2\2\2!$\7\f\2\2\"$\7\17"+
+ "\2\2#\37\3\2\2\2#\"\3\2\2\2$\f\3\2\2\2%&\t\4\2\2&\16\3\2\2\2\'(\n\5\2"+
+ "\2(\20\3\2\2\2\6\2\33\37#\2";
+ public static final ATN _ATN =
+ new ATNDeserializer().deserialize(_serializedATN.toCharArray());
+ static {
+ _decisionToDFA = new DFA[_ATN.getNumberOfDecisions()];
+ for (int i = 0; i < _ATN.getNumberOfDecisions(); i++) {
+ _decisionToDFA[i] = new DFA(_ATN.getDecisionState(i), i);
+ }
+ }
+}
\ No newline at end of file
diff --git a/vscode-extensions/commons/java-properties/src/main/java/org/springframework/ide/vscode/properties/antlr/parser/JavaPropertiesLexer.tokens b/vscode-extensions/commons/java-properties/src/main/java/org/springframework/ide/vscode/properties/antlr/parser/JavaPropertiesLexer.tokens
new file mode 100644
index 000000000..fe8593417
--- /dev/null
+++ b/vscode-extensions/commons/java-properties/src/main/java/org/springframework/ide/vscode/properties/antlr/parser/JavaPropertiesLexer.tokens
@@ -0,0 +1,10 @@
+Backslash=1
+Colon=2
+Equals=3
+Comment=4
+LineBreak=5
+Space=6
+IdentifierChar=7
+'\\'=1
+':'=2
+'='=3
diff --git a/vscode-extensions/commons/java-properties/src/main/java/org/springframework/ide/vscode/properties/antlr/parser/JavaPropertiesListener.java b/vscode-extensions/commons/java-properties/src/main/java/org/springframework/ide/vscode/properties/antlr/parser/JavaPropertiesListener.java
new file mode 100644
index 000000000..1227cdb6b
--- /dev/null
+++ b/vscode-extensions/commons/java-properties/src/main/java/org/springframework/ide/vscode/properties/antlr/parser/JavaPropertiesListener.java
@@ -0,0 +1,110 @@
+// Generated from JavaProperties.g4 by ANTLR 4.5.3
+package org.springframework.ide.vscode.properties.antlr.parser;
+import org.antlr.v4.runtime.tree.ParseTreeListener;
+
+/**
+ * This interface defines a complete listener for a parse tree produced by
+ * {@link JavaPropertiesParser}.
+ */
+public interface JavaPropertiesListener extends ParseTreeListener {
+ /**
+ * Enter a parse tree produced by {@link JavaPropertiesParser#parse}.
+ * @param ctx the parse tree
+ */
+ void enterParse(JavaPropertiesParser.ParseContext ctx);
+ /**
+ * Exit a parse tree produced by {@link JavaPropertiesParser#parse}.
+ * @param ctx the parse tree
+ */
+ void exitParse(JavaPropertiesParser.ParseContext ctx);
+ /**
+ * Enter a parse tree produced by {@link JavaPropertiesParser#line}.
+ * @param ctx the parse tree
+ */
+ void enterLine(JavaPropertiesParser.LineContext ctx);
+ /**
+ * Exit a parse tree produced by {@link JavaPropertiesParser#line}.
+ * @param ctx the parse tree
+ */
+ void exitLine(JavaPropertiesParser.LineContext ctx);
+ /**
+ * Enter a parse tree produced by {@link JavaPropertiesParser#propertyLine}.
+ * @param ctx the parse tree
+ */
+ void enterPropertyLine(JavaPropertiesParser.PropertyLineContext ctx);
+ /**
+ * Exit a parse tree produced by {@link JavaPropertiesParser#propertyLine}.
+ * @param ctx the parse tree
+ */
+ void exitPropertyLine(JavaPropertiesParser.PropertyLineContext ctx);
+ /**
+ * Enter a parse tree produced by {@link JavaPropertiesParser#commentLine}.
+ * @param ctx the parse tree
+ */
+ void enterCommentLine(JavaPropertiesParser.CommentLineContext ctx);
+ /**
+ * Exit a parse tree produced by {@link JavaPropertiesParser#commentLine}.
+ * @param ctx the parse tree
+ */
+ void exitCommentLine(JavaPropertiesParser.CommentLineContext ctx);
+ /**
+ * Enter a parse tree produced by {@link JavaPropertiesParser#emptyLine}.
+ * @param ctx the parse tree
+ */
+ void enterEmptyLine(JavaPropertiesParser.EmptyLineContext ctx);
+ /**
+ * Exit a parse tree produced by {@link JavaPropertiesParser#emptyLine}.
+ * @param ctx the parse tree
+ */
+ void exitEmptyLine(JavaPropertiesParser.EmptyLineContext ctx);
+ /**
+ * Enter a parse tree produced by {@link JavaPropertiesParser#keyValuePair}.
+ * @param ctx the parse tree
+ */
+ void enterKeyValuePair(JavaPropertiesParser.KeyValuePairContext ctx);
+ /**
+ * Exit a parse tree produced by {@link JavaPropertiesParser#keyValuePair}.
+ * @param ctx the parse tree
+ */
+ void exitKeyValuePair(JavaPropertiesParser.KeyValuePairContext ctx);
+ /**
+ * Enter a parse tree produced by {@link JavaPropertiesParser#key}.
+ * @param ctx the parse tree
+ */
+ void enterKey(JavaPropertiesParser.KeyContext ctx);
+ /**
+ * Exit a parse tree produced by {@link JavaPropertiesParser#key}.
+ * @param ctx the parse tree
+ */
+ void exitKey(JavaPropertiesParser.KeyContext ctx);
+ /**
+ * Enter a parse tree produced by {@link JavaPropertiesParser#keyChar}.
+ * @param ctx the parse tree
+ */
+ void enterKeyChar(JavaPropertiesParser.KeyCharContext ctx);
+ /**
+ * Exit a parse tree produced by {@link JavaPropertiesParser#keyChar}.
+ * @param ctx the parse tree
+ */
+ void exitKeyChar(JavaPropertiesParser.KeyCharContext ctx);
+ /**
+ * Enter a parse tree produced by {@link JavaPropertiesParser#separatorAndValue}.
+ * @param ctx the parse tree
+ */
+ void enterSeparatorAndValue(JavaPropertiesParser.SeparatorAndValueContext ctx);
+ /**
+ * Exit a parse tree produced by {@link JavaPropertiesParser#separatorAndValue}.
+ * @param ctx the parse tree
+ */
+ void exitSeparatorAndValue(JavaPropertiesParser.SeparatorAndValueContext ctx);
+ /**
+ * Enter a parse tree produced by {@link JavaPropertiesParser#valueChar}.
+ * @param ctx the parse tree
+ */
+ void enterValueChar(JavaPropertiesParser.ValueCharContext ctx);
+ /**
+ * Exit a parse tree produced by {@link JavaPropertiesParser#valueChar}.
+ * @param ctx the parse tree
+ */
+ void exitValueChar(JavaPropertiesParser.ValueCharContext ctx);
+}
\ No newline at end of file
diff --git a/vscode-extensions/commons/java-properties/src/main/java/org/springframework/ide/vscode/properties/antlr/parser/JavaPropertiesParser.java b/vscode-extensions/commons/java-properties/src/main/java/org/springframework/ide/vscode/properties/antlr/parser/JavaPropertiesParser.java
new file mode 100644
index 000000000..c6a97a7a4
--- /dev/null
+++ b/vscode-extensions/commons/java-properties/src/main/java/org/springframework/ide/vscode/properties/antlr/parser/JavaPropertiesParser.java
@@ -0,0 +1,735 @@
+// Generated from JavaProperties.g4 by ANTLR 4.5.3
+package org.springframework.ide.vscode.properties.antlr.parser;
+import org.antlr.v4.runtime.atn.*;
+import org.antlr.v4.runtime.dfa.DFA;
+import org.antlr.v4.runtime.*;
+import org.antlr.v4.runtime.misc.*;
+import org.antlr.v4.runtime.tree.*;
+import java.util.List;
+import java.util.Iterator;
+import java.util.ArrayList;
+
+@SuppressWarnings({"all", "warnings", "unchecked", "unused", "cast"})
+public class JavaPropertiesParser extends Parser {
+ static { RuntimeMetaData.checkVersion("4.5.3", RuntimeMetaData.VERSION); }
+
+ protected static final DFA[] _decisionToDFA;
+ protected static final PredictionContextCache _sharedContextCache =
+ new PredictionContextCache();
+ public static final int
+ Backslash=1, Colon=2, Equals=3, Comment=4, LineBreak=5, Space=6, IdentifierChar=7;
+ public static final int
+ RULE_parse = 0, RULE_line = 1, RULE_propertyLine = 2, RULE_commentLine = 3,
+ RULE_emptyLine = 4, RULE_keyValuePair = 5, RULE_key = 6, RULE_keyChar = 7,
+ RULE_separatorAndValue = 8, RULE_valueChar = 9;
+ public static final String[] ruleNames = {
+ "parse", "line", "propertyLine", "commentLine", "emptyLine", "keyValuePair",
+ "key", "keyChar", "separatorAndValue", "valueChar"
+ };
+
+ private static final String[] _LITERAL_NAMES = {
+ null, "'\\'", "':'", "'='"
+ };
+ private static final String[] _SYMBOLIC_NAMES = {
+ null, "Backslash", "Colon", "Equals", "Comment", "LineBreak", "Space",
+ "IdentifierChar"
+ };
+ public static final Vocabulary VOCABULARY = new VocabularyImpl(_LITERAL_NAMES, _SYMBOLIC_NAMES);
+
+ /**
+ * @deprecated Use {@link #VOCABULARY} instead.
+ */
+ @Deprecated
+ public static final String[] tokenNames;
+ static {
+ tokenNames = new String[_SYMBOLIC_NAMES.length];
+ for (int i = 0; i < tokenNames.length; i++) {
+ tokenNames[i] = VOCABULARY.getLiteralName(i);
+ if (tokenNames[i] == null) {
+ tokenNames[i] = VOCABULARY.getSymbolicName(i);
+ }
+
+ if (tokenNames[i] == null) {
+ tokenNames[i] = "";
+ }
+ }
+ }
+
+ @Override
+ @Deprecated
+ public String[] getTokenNames() {
+ return tokenNames;
+ }
+
+ @Override
+
+ public Vocabulary getVocabulary() {
+ return VOCABULARY;
+ }
+
+ @Override
+ public String getGrammarFileName() { return "JavaProperties.g4"; }
+
+ @Override
+ public String[] getRuleNames() { return ruleNames; }
+
+ @Override
+ public String getSerializedATN() { return _serializedATN; }
+
+ @Override
+ public ATN getATN() { return _ATN; }
+
+ public JavaPropertiesParser(TokenStream input) {
+ super(input);
+ _interp = new ParserATNSimulator(this,_ATN,_decisionToDFA,_sharedContextCache);
+ }
+ public static class ParseContext extends ParserRuleContext {
+ public TerminalNode EOF() { return getToken(JavaPropertiesParser.EOF, 0); }
+ public List line() {
+ return getRuleContexts(LineContext.class);
+ }
+ public LineContext line(int i) {
+ return getRuleContext(LineContext.class,i);
+ }
+ public ParseContext(ParserRuleContext parent, int invokingState) {
+ super(parent, invokingState);
+ }
+ @Override public int getRuleIndex() { return RULE_parse; }
+ @Override
+ public void enterRule(ParseTreeListener listener) {
+ if ( listener instanceof JavaPropertiesListener ) ((JavaPropertiesListener)listener).enterParse(this);
+ }
+ @Override
+ public void exitRule(ParseTreeListener listener) {
+ if ( listener instanceof JavaPropertiesListener ) ((JavaPropertiesListener)listener).exitParse(this);
+ }
+ }
+
+ public final ParseContext parse() throws RecognitionException {
+ ParseContext _localctx = new ParseContext(_ctx, getState());
+ enterRule(_localctx, 0, RULE_parse);
+ int _la;
+ try {
+ enterOuterAlt(_localctx, 1);
+ {
+ setState(23);
+ _errHandler.sync(this);
+ _la = _input.LA(1);
+ while ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << Backslash) | (1L << Comment) | (1L << LineBreak) | (1L << Space) | (1L << IdentifierChar))) != 0)) {
+ {
+ {
+ setState(20);
+ line();
+ }
+ }
+ setState(25);
+ _errHandler.sync(this);
+ _la = _input.LA(1);
+ }
+ setState(26);
+ match(EOF);
+ }
+ }
+ catch (RecognitionException re) {
+ _localctx.exception = re;
+ _errHandler.reportError(this, re);
+ _errHandler.recover(this, re);
+ }
+ finally {
+ exitRule();
+ }
+ return _localctx;
+ }
+
+ public static class LineContext extends ParserRuleContext {
+ public PropertyLineContext propertyLine() {
+ return getRuleContext(PropertyLineContext.class,0);
+ }
+ public CommentLineContext commentLine() {
+ return getRuleContext(CommentLineContext.class,0);
+ }
+ public EmptyLineContext emptyLine() {
+ return getRuleContext(EmptyLineContext.class,0);
+ }
+ public LineContext(ParserRuleContext parent, int invokingState) {
+ super(parent, invokingState);
+ }
+ @Override public int getRuleIndex() { return RULE_line; }
+ @Override
+ public void enterRule(ParseTreeListener listener) {
+ if ( listener instanceof JavaPropertiesListener ) ((JavaPropertiesListener)listener).enterLine(this);
+ }
+ @Override
+ public void exitRule(ParseTreeListener listener) {
+ if ( listener instanceof JavaPropertiesListener ) ((JavaPropertiesListener)listener).exitLine(this);
+ }
+ }
+
+ public final LineContext line() throws RecognitionException {
+ LineContext _localctx = new LineContext(_ctx, getState());
+ enterRule(_localctx, 2, RULE_line);
+ try {
+ setState(31);
+ _errHandler.sync(this);
+ switch ( getInterpreter().adaptivePredict(_input,1,_ctx) ) {
+ case 1:
+ enterOuterAlt(_localctx, 1);
+ {
+ setState(28);
+ propertyLine();
+ }
+ break;
+ case 2:
+ enterOuterAlt(_localctx, 2);
+ {
+ setState(29);
+ commentLine();
+ }
+ break;
+ case 3:
+ enterOuterAlt(_localctx, 3);
+ {
+ setState(30);
+ emptyLine();
+ }
+ break;
+ }
+ }
+ catch (RecognitionException re) {
+ _localctx.exception = re;
+ _errHandler.reportError(this, re);
+ _errHandler.recover(this, re);
+ }
+ finally {
+ exitRule();
+ }
+ return _localctx;
+ }
+
+ public static class PropertyLineContext extends ParserRuleContext {
+ public KeyValuePairContext keyValuePair() {
+ return getRuleContext(KeyValuePairContext.class,0);
+ }
+ public List Space() { return getTokens(JavaPropertiesParser.Space); }
+ public TerminalNode Space(int i) {
+ return getToken(JavaPropertiesParser.Space, i);
+ }
+ public PropertyLineContext(ParserRuleContext parent, int invokingState) {
+ super(parent, invokingState);
+ }
+ @Override public int getRuleIndex() { return RULE_propertyLine; }
+ @Override
+ public void enterRule(ParseTreeListener listener) {
+ if ( listener instanceof JavaPropertiesListener ) ((JavaPropertiesListener)listener).enterPropertyLine(this);
+ }
+ @Override
+ public void exitRule(ParseTreeListener listener) {
+ if ( listener instanceof JavaPropertiesListener ) ((JavaPropertiesListener)listener).exitPropertyLine(this);
+ }
+ }
+
+ public final PropertyLineContext propertyLine() throws RecognitionException {
+ PropertyLineContext _localctx = new PropertyLineContext(_ctx, getState());
+ enterRule(_localctx, 4, RULE_propertyLine);
+ int _la;
+ try {
+ enterOuterAlt(_localctx, 1);
+ {
+ setState(36);
+ _errHandler.sync(this);
+ _la = _input.LA(1);
+ while (_la==Space) {
+ {
+ {
+ setState(33);
+ match(Space);
+ }
+ }
+ setState(38);
+ _errHandler.sync(this);
+ _la = _input.LA(1);
+ }
+ setState(39);
+ keyValuePair();
+ }
+ }
+ catch (RecognitionException re) {
+ _localctx.exception = re;
+ _errHandler.reportError(this, re);
+ _errHandler.recover(this, re);
+ }
+ finally {
+ exitRule();
+ }
+ return _localctx;
+ }
+
+ public static class CommentLineContext extends ParserRuleContext {
+ public TerminalNode Comment() { return getToken(JavaPropertiesParser.Comment, 0); }
+ public TerminalNode LineBreak() { return getToken(JavaPropertiesParser.LineBreak, 0); }
+ public TerminalNode EOF() { return getToken(JavaPropertiesParser.EOF, 0); }
+ public List Space() { return getTokens(JavaPropertiesParser.Space); }
+ public TerminalNode Space(int i) {
+ return getToken(JavaPropertiesParser.Space, i);
+ }
+ public CommentLineContext(ParserRuleContext parent, int invokingState) {
+ super(parent, invokingState);
+ }
+ @Override public int getRuleIndex() { return RULE_commentLine; }
+ @Override
+ public void enterRule(ParseTreeListener listener) {
+ if ( listener instanceof JavaPropertiesListener ) ((JavaPropertiesListener)listener).enterCommentLine(this);
+ }
+ @Override
+ public void exitRule(ParseTreeListener listener) {
+ if ( listener instanceof JavaPropertiesListener ) ((JavaPropertiesListener)listener).exitCommentLine(this);
+ }
+ }
+
+ public final CommentLineContext commentLine() throws RecognitionException {
+ CommentLineContext _localctx = new CommentLineContext(_ctx, getState());
+ enterRule(_localctx, 6, RULE_commentLine);
+ int _la;
+ try {
+ enterOuterAlt(_localctx, 1);
+ {
+ setState(44);
+ _errHandler.sync(this);
+ _la = _input.LA(1);
+ while (_la==Space) {
+ {
+ {
+ setState(41);
+ match(Space);
+ }
+ }
+ setState(46);
+ _errHandler.sync(this);
+ _la = _input.LA(1);
+ }
+ setState(47);
+ match(Comment);
+ setState(48);
+ _la = _input.LA(1);
+ if ( !(_la==EOF || _la==LineBreak) ) {
+ _errHandler.recoverInline(this);
+ } else {
+ consume();
+ }
+ }
+ }
+ catch (RecognitionException re) {
+ _localctx.exception = re;
+ _errHandler.reportError(this, re);
+ _errHandler.recover(this, re);
+ }
+ finally {
+ exitRule();
+ }
+ return _localctx;
+ }
+
+ public static class EmptyLineContext extends ParserRuleContext {
+ public TerminalNode LineBreak() { return getToken(JavaPropertiesParser.LineBreak, 0); }
+ public List Space() { return getTokens(JavaPropertiesParser.Space); }
+ public TerminalNode Space(int i) {
+ return getToken(JavaPropertiesParser.Space, i);
+ }
+ public EmptyLineContext(ParserRuleContext parent, int invokingState) {
+ super(parent, invokingState);
+ }
+ @Override public int getRuleIndex() { return RULE_emptyLine; }
+ @Override
+ public void enterRule(ParseTreeListener listener) {
+ if ( listener instanceof JavaPropertiesListener ) ((JavaPropertiesListener)listener).enterEmptyLine(this);
+ }
+ @Override
+ public void exitRule(ParseTreeListener listener) {
+ if ( listener instanceof JavaPropertiesListener ) ((JavaPropertiesListener)listener).exitEmptyLine(this);
+ }
+ }
+
+ public final EmptyLineContext emptyLine() throws RecognitionException {
+ EmptyLineContext _localctx = new EmptyLineContext(_ctx, getState());
+ enterRule(_localctx, 8, RULE_emptyLine);
+ int _la;
+ try {
+ enterOuterAlt(_localctx, 1);
+ {
+ setState(53);
+ _errHandler.sync(this);
+ _la = _input.LA(1);
+ while (_la==Space) {
+ {
+ {
+ setState(50);
+ match(Space);
+ }
+ }
+ setState(55);
+ _errHandler.sync(this);
+ _la = _input.LA(1);
+ }
+ setState(56);
+ match(LineBreak);
+ }
+ }
+ catch (RecognitionException re) {
+ _localctx.exception = re;
+ _errHandler.reportError(this, re);
+ _errHandler.recover(this, re);
+ }
+ finally {
+ exitRule();
+ }
+ return _localctx;
+ }
+
+ public static class KeyValuePairContext extends ParserRuleContext {
+ public KeyContext key() {
+ return getRuleContext(KeyContext.class,0);
+ }
+ public SeparatorAndValueContext separatorAndValue() {
+ return getRuleContext(SeparatorAndValueContext.class,0);
+ }
+ public TerminalNode LineBreak() { return getToken(JavaPropertiesParser.LineBreak, 0); }
+ public TerminalNode EOF() { return getToken(JavaPropertiesParser.EOF, 0); }
+ public KeyValuePairContext(ParserRuleContext parent, int invokingState) {
+ super(parent, invokingState);
+ }
+ @Override public int getRuleIndex() { return RULE_keyValuePair; }
+ @Override
+ public void enterRule(ParseTreeListener listener) {
+ if ( listener instanceof JavaPropertiesListener ) ((JavaPropertiesListener)listener).enterKeyValuePair(this);
+ }
+ @Override
+ public void exitRule(ParseTreeListener listener) {
+ if ( listener instanceof JavaPropertiesListener ) ((JavaPropertiesListener)listener).exitKeyValuePair(this);
+ }
+ }
+
+ public final KeyValuePairContext keyValuePair() throws RecognitionException {
+ KeyValuePairContext _localctx = new KeyValuePairContext(_ctx, getState());
+ enterRule(_localctx, 10, RULE_keyValuePair);
+ int _la;
+ try {
+ enterOuterAlt(_localctx, 1);
+ {
+ setState(58);
+ key();
+ setState(59);
+ separatorAndValue();
+ setState(60);
+ _la = _input.LA(1);
+ if ( !(_la==EOF || _la==LineBreak) ) {
+ _errHandler.recoverInline(this);
+ } else {
+ consume();
+ }
+ }
+ }
+ catch (RecognitionException re) {
+ _localctx.exception = re;
+ _errHandler.reportError(this, re);
+ _errHandler.recover(this, re);
+ }
+ finally {
+ exitRule();
+ }
+ return _localctx;
+ }
+
+ public static class KeyContext extends ParserRuleContext {
+ public List keyChar() {
+ return getRuleContexts(KeyCharContext.class);
+ }
+ public KeyCharContext keyChar(int i) {
+ return getRuleContext(KeyCharContext.class,i);
+ }
+ public KeyContext(ParserRuleContext parent, int invokingState) {
+ super(parent, invokingState);
+ }
+ @Override public int getRuleIndex() { return RULE_key; }
+ @Override
+ public void enterRule(ParseTreeListener listener) {
+ if ( listener instanceof JavaPropertiesListener ) ((JavaPropertiesListener)listener).enterKey(this);
+ }
+ @Override
+ public void exitRule(ParseTreeListener listener) {
+ if ( listener instanceof JavaPropertiesListener ) ((JavaPropertiesListener)listener).exitKey(this);
+ }
+ }
+
+ public final KeyContext key() throws RecognitionException {
+ KeyContext _localctx = new KeyContext(_ctx, getState());
+ enterRule(_localctx, 12, RULE_key);
+ int _la;
+ try {
+ enterOuterAlt(_localctx, 1);
+ {
+ setState(63);
+ _errHandler.sync(this);
+ _la = _input.LA(1);
+ do {
+ {
+ {
+ setState(62);
+ keyChar();
+ }
+ }
+ setState(65);
+ _errHandler.sync(this);
+ _la = _input.LA(1);
+ } while ( _la==Backslash || _la==IdentifierChar );
+ }
+ }
+ catch (RecognitionException re) {
+ _localctx.exception = re;
+ _errHandler.reportError(this, re);
+ _errHandler.recover(this, re);
+ }
+ finally {
+ exitRule();
+ }
+ return _localctx;
+ }
+
+ public static class KeyCharContext extends ParserRuleContext {
+ public TerminalNode IdentifierChar() { return getToken(JavaPropertiesParser.IdentifierChar, 0); }
+ public TerminalNode Backslash() { return getToken(JavaPropertiesParser.Backslash, 0); }
+ public TerminalNode Colon() { return getToken(JavaPropertiesParser.Colon, 0); }
+ public TerminalNode Equals() { return getToken(JavaPropertiesParser.Equals, 0); }
+ public KeyCharContext(ParserRuleContext parent, int invokingState) {
+ super(parent, invokingState);
+ }
+ @Override public int getRuleIndex() { return RULE_keyChar; }
+ @Override
+ public void enterRule(ParseTreeListener listener) {
+ if ( listener instanceof JavaPropertiesListener ) ((JavaPropertiesListener)listener).enterKeyChar(this);
+ }
+ @Override
+ public void exitRule(ParseTreeListener listener) {
+ if ( listener instanceof JavaPropertiesListener ) ((JavaPropertiesListener)listener).exitKeyChar(this);
+ }
+ }
+
+ public final KeyCharContext keyChar() throws RecognitionException {
+ KeyCharContext _localctx = new KeyCharContext(_ctx, getState());
+ enterRule(_localctx, 14, RULE_keyChar);
+ int _la;
+ try {
+ setState(70);
+ switch (_input.LA(1)) {
+ case IdentifierChar:
+ enterOuterAlt(_localctx, 1);
+ {
+ setState(67);
+ match(IdentifierChar);
+ }
+ break;
+ case Backslash:
+ enterOuterAlt(_localctx, 2);
+ {
+ setState(68);
+ match(Backslash);
+ setState(69);
+ _la = _input.LA(1);
+ if ( !(_la==Colon || _la==Equals) ) {
+ _errHandler.recoverInline(this);
+ } else {
+ consume();
+ }
+ }
+ break;
+ default:
+ throw new NoViableAltException(this);
+ }
+ }
+ catch (RecognitionException re) {
+ _localctx.exception = re;
+ _errHandler.reportError(this, re);
+ _errHandler.recover(this, re);
+ }
+ finally {
+ exitRule();
+ }
+ return _localctx;
+ }
+
+ public static class SeparatorAndValueContext extends ParserRuleContext {
+ public TerminalNode Space() { return getToken(JavaPropertiesParser.Space, 0); }
+ public TerminalNode Colon() { return getToken(JavaPropertiesParser.Colon, 0); }
+ public TerminalNode Equals() { return getToken(JavaPropertiesParser.Equals, 0); }
+ public List valueChar() {
+ return getRuleContexts(ValueCharContext.class);
+ }
+ public ValueCharContext valueChar(int i) {
+ return getRuleContext(ValueCharContext.class,i);
+ }
+ public SeparatorAndValueContext(ParserRuleContext parent, int invokingState) {
+ super(parent, invokingState);
+ }
+ @Override public int getRuleIndex() { return RULE_separatorAndValue; }
+ @Override
+ public void enterRule(ParseTreeListener listener) {
+ if ( listener instanceof JavaPropertiesListener ) ((JavaPropertiesListener)listener).enterSeparatorAndValue(this);
+ }
+ @Override
+ public void exitRule(ParseTreeListener listener) {
+ if ( listener instanceof JavaPropertiesListener ) ((JavaPropertiesListener)listener).exitSeparatorAndValue(this);
+ }
+ }
+
+ public final SeparatorAndValueContext separatorAndValue() throws RecognitionException {
+ SeparatorAndValueContext _localctx = new SeparatorAndValueContext(_ctx, getState());
+ enterRule(_localctx, 16, RULE_separatorAndValue);
+ int _la;
+ try {
+ enterOuterAlt(_localctx, 1);
+ {
+ setState(72);
+ _la = _input.LA(1);
+ if ( !((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << Colon) | (1L << Equals) | (1L << Space))) != 0)) ) {
+ _errHandler.recoverInline(this);
+ } else {
+ consume();
+ }
+ setState(74);
+ _errHandler.sync(this);
+ _la = _input.LA(1);
+ do {
+ {
+ {
+ setState(73);
+ valueChar();
+ }
+ }
+ setState(76);
+ _errHandler.sync(this);
+ _la = _input.LA(1);
+ } while ( (((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << Backslash) | (1L << Colon) | (1L << Equals) | (1L << Space) | (1L << IdentifierChar))) != 0) );
+ }
+ }
+ catch (RecognitionException re) {
+ _localctx.exception = re;
+ _errHandler.reportError(this, re);
+ _errHandler.recover(this, re);
+ }
+ finally {
+ exitRule();
+ }
+ return _localctx;
+ }
+
+ public static class ValueCharContext extends ParserRuleContext {
+ public TerminalNode IdentifierChar() { return getToken(JavaPropertiesParser.IdentifierChar, 0); }
+ public TerminalNode Space() { return getToken(JavaPropertiesParser.Space, 0); }
+ public TerminalNode Backslash() { return getToken(JavaPropertiesParser.Backslash, 0); }
+ public TerminalNode LineBreak() { return getToken(JavaPropertiesParser.LineBreak, 0); }
+ public TerminalNode Equals() { return getToken(JavaPropertiesParser.Equals, 0); }
+ public TerminalNode Colon() { return getToken(JavaPropertiesParser.Colon, 0); }
+ public ValueCharContext(ParserRuleContext parent, int invokingState) {
+ super(parent, invokingState);
+ }
+ @Override public int getRuleIndex() { return RULE_valueChar; }
+ @Override
+ public void enterRule(ParseTreeListener listener) {
+ if ( listener instanceof JavaPropertiesListener ) ((JavaPropertiesListener)listener).enterValueChar(this);
+ }
+ @Override
+ public void exitRule(ParseTreeListener listener) {
+ if ( listener instanceof JavaPropertiesListener ) ((JavaPropertiesListener)listener).exitValueChar(this);
+ }
+ }
+
+ public final ValueCharContext valueChar() throws RecognitionException {
+ ValueCharContext _localctx = new ValueCharContext(_ctx, getState());
+ enterRule(_localctx, 18, RULE_valueChar);
+ try {
+ setState(84);
+ switch (_input.LA(1)) {
+ case IdentifierChar:
+ enterOuterAlt(_localctx, 1);
+ {
+ setState(78);
+ match(IdentifierChar);
+ }
+ break;
+ case Space:
+ enterOuterAlt(_localctx, 2);
+ {
+ setState(79);
+ match(Space);
+ }
+ break;
+ case Backslash:
+ enterOuterAlt(_localctx, 3);
+ {
+ setState(80);
+ match(Backslash);
+ setState(81);
+ match(LineBreak);
+ }
+ break;
+ case Equals:
+ enterOuterAlt(_localctx, 4);
+ {
+ setState(82);
+ match(Equals);
+ }
+ break;
+ case Colon:
+ enterOuterAlt(_localctx, 5);
+ {
+ setState(83);
+ match(Colon);
+ }
+ break;
+ default:
+ throw new NoViableAltException(this);
+ }
+ }
+ catch (RecognitionException re) {
+ _localctx.exception = re;
+ _errHandler.reportError(this, re);
+ _errHandler.recover(this, re);
+ }
+ finally {
+ exitRule();
+ }
+ return _localctx;
+ }
+
+ public static final String _serializedATN =
+ "\3\u0430\ud6d1\u8206\uad2d\u4417\uaef1\u8d80\uaadd\3\tY\4\2\t\2\4\3\t"+
+ "\3\4\4\t\4\4\5\t\5\4\6\t\6\4\7\t\7\4\b\t\b\4\t\t\t\4\n\t\n\4\13\t\13\3"+
+ "\2\7\2\30\n\2\f\2\16\2\33\13\2\3\2\3\2\3\3\3\3\3\3\5\3\"\n\3\3\4\7\4%"+
+ "\n\4\f\4\16\4(\13\4\3\4\3\4\3\5\7\5-\n\5\f\5\16\5\60\13\5\3\5\3\5\3\5"+
+ "\3\6\7\6\66\n\6\f\6\16\69\13\6\3\6\3\6\3\7\3\7\3\7\3\7\3\b\6\bB\n\b\r"+
+ "\b\16\bC\3\t\3\t\3\t\5\tI\n\t\3\n\3\n\6\nM\n\n\r\n\16\nN\3\13\3\13\3\13"+
+ "\3\13\3\13\3\13\5\13W\n\13\3\13\2\2\f\2\4\6\b\n\f\16\20\22\24\2\5\3\3"+
+ "\7\7\3\2\4\5\4\2\4\5\b\b[\2\31\3\2\2\2\4!\3\2\2\2\6&\3\2\2\2\b.\3\2\2"+
+ "\2\n\67\3\2\2\2\f<\3\2\2\2\16A\3\2\2\2\20H\3\2\2\2\22J\3\2\2\2\24V\3\2"+
+ "\2\2\26\30\5\4\3\2\27\26\3\2\2\2\30\33\3\2\2\2\31\27\3\2\2\2\31\32\3\2"+
+ "\2\2\32\34\3\2\2\2\33\31\3\2\2\2\34\35\7\2\2\3\35\3\3\2\2\2\36\"\5\6\4"+
+ "\2\37\"\5\b\5\2 \"\5\n\6\2!\36\3\2\2\2!\37\3\2\2\2! \3\2\2\2\"\5\3\2\2"+
+ "\2#%\7\b\2\2$#\3\2\2\2%(\3\2\2\2&$\3\2\2\2&\'\3\2\2\2\')\3\2\2\2(&\3\2"+
+ "\2\2)*\5\f\7\2*\7\3\2\2\2+-\7\b\2\2,+\3\2\2\2-\60\3\2\2\2.,\3\2\2\2./"+
+ "\3\2\2\2/\61\3\2\2\2\60.\3\2\2\2\61\62\7\6\2\2\62\63\t\2\2\2\63\t\3\2"+
+ "\2\2\64\66\7\b\2\2\65\64\3\2\2\2\669\3\2\2\2\67\65\3\2\2\2\678\3\2\2\2"+
+ "8:\3\2\2\29\67\3\2\2\2:;\7\7\2\2;\13\3\2\2\2<=\5\16\b\2=>\5\22\n\2>?\t"+
+ "\2\2\2?\r\3\2\2\2@B\5\20\t\2A@\3\2\2\2BC\3\2\2\2CA\3\2\2\2CD\3\2\2\2D"+
+ "\17\3\2\2\2EI\7\t\2\2FG\7\3\2\2GI\t\3\2\2HE\3\2\2\2HF\3\2\2\2I\21\3\2"+
+ "\2\2JL\t\4\2\2KM\5\24\13\2LK\3\2\2\2MN\3\2\2\2NL\3\2\2\2NO\3\2\2\2O\23"+
+ "\3\2\2\2PW\7\t\2\2QW\7\b\2\2RS\7\3\2\2SW\7\7\2\2TW\7\5\2\2UW\7\4\2\2V"+
+ "P\3\2\2\2VQ\3\2\2\2VR\3\2\2\2VT\3\2\2\2VU\3\2\2\2W\25\3\2\2\2\13\31!&"+
+ ".\67CHNV";
+ public static final ATN _ATN =
+ new ATNDeserializer().deserialize(_serializedATN.toCharArray());
+ static {
+ _decisionToDFA = new DFA[_ATN.getNumberOfDecisions()];
+ for (int i = 0; i < _ATN.getNumberOfDecisions(); i++) {
+ _decisionToDFA[i] = new DFA(_ATN.getDecisionState(i), i);
+ }
+ }
+}
\ No newline at end of file
diff --git a/vscode-extensions/commons/java-properties/src/main/java/org/springframework/ide/vscode/properties/parser/ParseResults.java b/vscode-extensions/commons/java-properties/src/main/java/org/springframework/ide/vscode/properties/parser/ParseResults.java
new file mode 100644
index 000000000..23fbc4dd6
--- /dev/null
+++ b/vscode-extensions/commons/java-properties/src/main/java/org/springframework/ide/vscode/properties/parser/ParseResults.java
@@ -0,0 +1,44 @@
+/*******************************************************************************
+ * Copyright (c) 2016 Pivotal, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Pivotal, Inc. - initial API and implementation
+ *******************************************************************************/
+package org.springframework.ide.vscode.properties.parser;
+
+import java.util.List;
+
+/**
+ * Results of parsing a text as Java Properties
+ *
+ * @author Alex Boyko
+ *
+ */
+public final class ParseResults {
+
+ /**
+ * Resultant AST created based on parse tree
+ */
+ final public PropertiesAst ast;
+
+ /**
+ * Any syntax errors discovered by the parser
+ */
+ final public List syntaxErrors;
+
+ /**
+ * Any non-syntax problems discovered during parsing i.e. possible grammar problems such as ambiguity etc.
+ */
+ final public List problems;
+
+ public ParseResults(PropertiesAst ast, List syntaxErrors, List problems) {
+ this.ast = ast;
+ this.syntaxErrors = syntaxErrors;
+ this.problems = problems;
+ }
+
+}
diff --git a/vscode-extensions/commons/java-properties/src/main/java/org/springframework/ide/vscode/properties/parser/Parser.java b/vscode-extensions/commons/java-properties/src/main/java/org/springframework/ide/vscode/properties/parser/Parser.java
new file mode 100644
index 000000000..375224c7b
--- /dev/null
+++ b/vscode-extensions/commons/java-properties/src/main/java/org/springframework/ide/vscode/properties/parser/Parser.java
@@ -0,0 +1,29 @@
+/*******************************************************************************
+ * Copyright (c) 2016 Pivotal, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Pivotal, Inc. - initial API and implementation
+ *******************************************************************************/
+package org.springframework.ide.vscode.properties.parser;
+
+/**
+ * Basic Parser interface
+ *
+ * @author Alex Boyko
+ *
+ */
+public interface Parser {
+
+ /**
+ * Parses passed in text based on Java Properties format
+ *
+ * @param text Text to parse
+ * @return Results of the parsing. See {@link ParseResults}
+ */
+ ParseResults parse(String text);
+
+}
diff --git a/vscode-extensions/commons/java-properties/src/main/java/org/springframework/ide/vscode/properties/parser/Problem.java b/vscode-extensions/commons/java-properties/src/main/java/org/springframework/ide/vscode/properties/parser/Problem.java
new file mode 100644
index 000000000..c6f2abe1f
--- /dev/null
+++ b/vscode-extensions/commons/java-properties/src/main/java/org/springframework/ide/vscode/properties/parser/Problem.java
@@ -0,0 +1,45 @@
+/*******************************************************************************
+ * Copyright (c) 2016 Pivotal, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Pivotal, Inc. - initial API and implementation
+ *******************************************************************************/
+package org.springframework.ide.vscode.properties.parser;
+
+/**
+ * Parsing problem interface
+ *
+ * @author Alex Boyko
+ *
+ */
+public interface Problem {
+
+ /**
+ * The parsing problem message
+ * @return The message string
+ */
+ String getMessage();
+
+ /**
+ * Problem's code
+ * @return The code
+ */
+ String getCode();
+
+ /**
+ * Problem's start index in the document
+ * @return Start index relative to the document
+ */
+ int getOffset();
+
+ /**
+ * Problem's range in symbols
+ * @return Number of characters
+ */
+ int getLength();
+
+}
diff --git a/vscode-extensions/commons/java-properties/src/main/java/org/springframework/ide/vscode/properties/parser/ProblemCodes.java b/vscode-extensions/commons/java-properties/src/main/java/org/springframework/ide/vscode/properties/parser/ProblemCodes.java
new file mode 100644
index 000000000..0c641b0d5
--- /dev/null
+++ b/vscode-extensions/commons/java-properties/src/main/java/org/springframework/ide/vscode/properties/parser/ProblemCodes.java
@@ -0,0 +1,24 @@
+/*******************************************************************************
+ * Copyright (c) 2016 Pivotal, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Pivotal, Inc. - initial API and implementation
+ *******************************************************************************/
+package org.springframework.ide.vscode.properties.parser;
+
+/**
+ * Parsing error codes
+ *
+ * @author Alex Boyko
+ *
+ */
+public class ProblemCodes {
+ public static final String PROPERTIES_SYNTAX_ERROR = "PROPERTIES_SYNTAX_ERROR";
+ public static final String PROPERTIES_AMBIGUITY_ERROR = "AMBIGUITY_ERROR";
+ public static final String PROPERTIES_FULL_CONTEXT_ERROR = "FULL_CONTEXT_ERROR";
+ public static final String PROPERTIES_CONTEXT_SENSITIVITY_ERROR = "CONTEXT_SENSITIVITY_ERROR";
+}
diff --git a/vscode-extensions/commons/java-properties/src/main/java/org/springframework/ide/vscode/properties/parser/PropertiesAst.java b/vscode-extensions/commons/java-properties/src/main/java/org/springframework/ide/vscode/properties/parser/PropertiesAst.java
new file mode 100644
index 000000000..c5692e5fc
--- /dev/null
+++ b/vscode-extensions/commons/java-properties/src/main/java/org/springframework/ide/vscode/properties/parser/PropertiesAst.java
@@ -0,0 +1,122 @@
+/*******************************************************************************
+ * Copyright (c) 2016 Pivotal, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Pivotal, Inc. - initial API and implementation
+ *******************************************************************************/
+package org.springframework.ide.vscode.properties.parser;
+
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * Very basic AST for Java Properties to keep comments and key value pairs
+ *
+ * @author Alex Boyko
+ *
+ */
+public final class PropertiesAst {
+
+ private List nodes;
+
+ public PropertiesAst(List nodes) {
+ this.nodes = nodes;
+ }
+
+ /**
+ * Retrieves all AST nodes
+ * @return List of AST nodes sorted by line number
+ */
+ public List extends Node> getAllNodes() {
+ return nodes;
+ }
+
+ /**
+ * Retrieves AST nodes of specific type
+ * @param clazz Type of AST nodes
+ * @return List of AST nodes of specific type sorted by line number
+ */
+ @SuppressWarnings("unchecked")
+ public List getNodes(Class clazz) {
+ List l = nodes.stream().filter(line -> {
+ return clazz.isAssignableFrom(line.getClass());
+ }).collect(Collectors.toList());
+ return (List) l;
+ }
+
+ /**
+ * Java Properties AST node
+ */
+ public interface Node {
+
+ /**
+ * Offset index of a node in the document
+ * @return Offset index
+ */
+ int getOffset();
+
+ /**
+ * Number of characters a node occupies in the document
+ * @return Number of characters
+ */
+ int getLength();
+
+ }
+
+ /**
+ * AST node for comment
+ */
+ public interface Comment extends Node {
+
+ }
+
+ /**
+ * AST node for property key and property value pair
+ */
+ public interface KeyValuePair extends Node {
+
+ /**
+ * AST node for key
+ * @return Node for key
+ */
+ Key getKey();
+
+ /**
+ * AST node for value
+ * @return Node for value
+ */
+ Value getValue();
+
+ }
+
+ /**
+ * AST node for property key
+ */
+ public interface Key extends Node {
+
+ /**
+ * Decode possibly encoded property name
+ * @return Decoded property name
+ */
+ String decode();
+
+ }
+
+ /**
+ * AST node for property value
+ */
+ public interface Value extends Node {
+
+ /**
+ * Decode possibly encoded property value
+ * @return Decoded property value
+ */
+ String decode();
+
+ }
+
+}
diff --git a/vscode-extensions/commons/java-properties/src/test/java/org/springframework/ide/vscode/parser/test/PropertiesAntlrParserTest.java b/vscode-extensions/commons/java-properties/src/test/java/org/springframework/ide/vscode/parser/test/PropertiesAntlrParserTest.java
new file mode 100644
index 000000000..1b5d39bfd
--- /dev/null
+++ b/vscode-extensions/commons/java-properties/src/test/java/org/springframework/ide/vscode/parser/test/PropertiesAntlrParserTest.java
@@ -0,0 +1,222 @@
+/*******************************************************************************
+ * Copyright (c) 2016 Pivotal, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Pivotal, Inc. - initial API and implementation
+ *******************************************************************************/
+package org.springframework.ide.vscode.parser.test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import java.util.List;
+
+import org.junit.Test;
+import org.springframework.ide.vscode.properties.antlr.parser.AntlrParser;
+import org.springframework.ide.vscode.properties.parser.ParseResults;
+import org.springframework.ide.vscode.properties.parser.Parser;
+import org.springframework.ide.vscode.properties.parser.Problem;
+import org.springframework.ide.vscode.properties.parser.PropertiesAst.Comment;
+import org.springframework.ide.vscode.properties.parser.PropertiesAst.KeyValuePair;
+
+public class PropertiesAntlrParserTest {
+
+ Parser parser = new AntlrParser();
+
+ private void testCommentLine(String text, String expectedComment) {
+ ParseResults results = parser.parse(text);
+ assertTrue(results.syntaxErrors.isEmpty());
+ assertTrue(results.problems.isEmpty());
+ assertEquals(1, results.ast.getAllNodes().size());
+
+ List commentLines = results.ast.getNodes(Comment.class);
+ assertEquals(1, commentLines.size());
+
+ Comment comment = commentLines.get(0);
+ assertEquals(expectedComment, text.substring(comment.getOffset(), comment.getOffset() + comment.getLength()));
+ }
+
+ private void testPropertyLine(String text,
+ String expectedKey, String expectedEncodedKey,
+ String expectedValue, String expectedEncodedValue) {
+ ParseResults results = parser.parse(text);
+ assertTrue(results.syntaxErrors.isEmpty());
+ assertTrue(results.problems.isEmpty());
+ assertEquals(1, results.ast.getAllNodes().size());
+
+ List propertyLines = results.ast.getNodes(KeyValuePair.class);
+ assertEquals(1, propertyLines.size());
+
+ KeyValuePair line = propertyLines.get(0);
+
+ assertNotNull(line.getKey());
+ assertNotNull(line.getValue());
+
+ assertEquals(expectedKey, line.getKey().decode());
+ assertEquals(expectedValue, line.getValue().decode());
+ assertEquals(expectedEncodedKey, text.substring(line.getKey().getOffset(), line.getKey().getOffset() + line.getKey().getLength()));
+ assertEquals(expectedEncodedValue, text.substring(line.getValue().getOffset(), line.getValue().getOffset() + line.getValue().getLength()));
+ }
+
+ @Test
+ public void testExclamationComment() throws Exception {
+ testCommentLine("! This is comment", "! This is comment");
+ }
+
+ @Test
+ public void testExclamationCommentWithSpaces() throws Exception {
+ testCommentLine(" ! This is comment = ", "! This is comment = ");
+ }
+
+ @Test
+ public void testSharpComment() throws Exception {
+ testCommentLine("# This is comment", "# This is comment");
+ }
+
+ @Test
+ public void testSharpCommentWithSpaces() throws Exception {
+ testCommentLine(" # This is comment = ", "# This is comment = ");
+ }
+
+ @Test
+ public void testLines1() throws Exception {
+ ParseResults results = parser.parse("# Comment\n\n \t \t \n\t\t\n");
+ assertTrue(results.syntaxErrors.isEmpty());
+ assertTrue(results.problems.isEmpty());
+ assertEquals(1, results.ast.getAllNodes().size());
+ assertEquals(1, results.ast.getNodes(Comment.class).size());
+ }
+
+ @Test
+ public void testLines2() throws Exception {
+ ParseResults results = parser.parse("\n\n \t \t \n# Comment\n\t\t\n");
+ assertTrue(results.syntaxErrors.isEmpty());
+ assertTrue(results.problems.isEmpty());
+ assertEquals(1, results.ast.getAllNodes().size());
+ assertEquals(1, results.ast.getNodes(Comment.class).size());
+ }
+
+ @Test
+ public void testLines3() throws Exception {
+ ParseResults results = parser.parse("# Comment\n\nkey = value 1 \n \t \t \n\t\t\n");
+ assertTrue(results.syntaxErrors.isEmpty());
+ assertTrue(results.problems.isEmpty());
+ assertEquals(2, results.ast.getAllNodes().size());
+ assertEquals(1, results.ast.getNodes(Comment.class).size());
+ assertEquals(1, results.ast.getNodes(KeyValuePair.class).size());
+ }
+
+ @Test
+ public void testPropertyWithEqualsSeparator() throws Exception {
+ testPropertyLine("key=value", "key", "key", "value", "value");
+ }
+
+ @Test
+ public void testPropertyWithEqualsSeparatorAndSpaces() throws Exception {
+ testPropertyLine("key \t = \t \tvalue", "key", "key", "value", "value");
+ }
+
+ @Test
+ public void testPropertyWithColonSeparator() throws Exception {
+ testPropertyLine("key:value", "key", "key", "value", "value");
+ }
+
+ @Test
+ public void testPropertyWithColonSeparatorAndSpaces() throws Exception {
+ testPropertyLine("key \t : \t \tvalue", "key", "key", "value", "value");
+ }
+
+ @Test
+ public void testPropertyWithSpaceSeparator() throws Exception {
+ testPropertyLine("key value", "key", "key", "value", "value");
+ }
+
+ @Test
+ public void testSpacesSeparation() throws Exception {
+ testPropertyLine("key \t value", "key", "key", "value", "value");
+ }
+
+ @Test
+ public void testValueWithSpaces() throws Exception {
+ testPropertyLine("key=value 1 and more staff \t that is all", "key", "key", "value 1 and more staff \t that is all", "value 1 and more staff \t that is all");
+ }
+
+ @Test
+ public void testKeyWithLeadingSpaces() throws Exception {
+ testPropertyLine(" key2:value 2", "key2", "key2", "value 2", "value 2");
+ }
+
+ @Test
+ public void testKeyWithLeadingAndTrailingSpaces() throws Exception {
+ testPropertyLine(" key3 \t :value3", "key3", "key3", "value3", "value3");
+ }
+
+ @Test
+ public void testEncodedKeyAndValue() throws Exception {
+ testPropertyLine("ke\\:\\=y4=v\\\na\\\nl\\\nu\\\ne \t 4", "ke:=y4", "ke\\:\\=y4", "value \t 4", "v\\\na\\\nl\\\nu\\\ne \t 4");
+ }
+
+ @Test
+ public void testEqualsValue() throws Exception {
+ testPropertyLine("key\\=5==", "key=5", "key\\=5", "=", "=");
+ }
+
+ @Test
+ public void testEqualsValueSeparatedWithEqualsAndSpace() throws Exception {
+ testPropertyLine("key7 = =", "key7", "key7", "=", "=");
+ }
+
+ @Test
+ public void testValueWithTrailingSpaces() throws Exception {
+ testPropertyLine("key = value 1 ", "key", "key", "value 1 ", "value 1 ");
+ }
+
+ @Test
+ public void testUnodeCharKeyAndValue() throws Exception {
+ testPropertyLine("k\u2b22ey\u2b28 = val\u2b24ue 1\u2b24 ", "k\u2b22ey\u2b28", "k\u2b22ey\u2b28", "val\u2b24ue 1\u2b24 ", "val\u2b24ue 1\u2b24 ");
+ }
+
+ @Test
+ public void testSyntaxError() throws Exception {
+ String text = "abrakadabra";
+ ParseResults results = parser.parse(text);
+ assertEquals(1, results.syntaxErrors.size());
+ assertTrue(results.problems.isEmpty());
+ // One property line recorded. With key and empty value
+ assertEquals(1, results.ast.getAllNodes().size());
+
+ Problem syntaxError = results.syntaxErrors.get(0);
+ assertEquals(text.length(), syntaxError.getOffset());
+ }
+
+ @Test
+ public void testMultipleSyntaxErrors() throws Exception {
+ String text = "abrakadabra\nkey:value\nsdcsdc";
+ ParseResults results = parser.parse(text);
+ assertEquals(2, results.syntaxErrors.size());
+ assertTrue(results.problems.isEmpty());
+ // One property line recorded. With key and empty value
+ assertEquals(3, results.ast.getAllNodes().size());
+ List lines = results.ast.getNodes(KeyValuePair.class);
+ assertEquals(3, lines.size());
+
+ // Test valid part
+ KeyValuePair validLine = lines.get(1);
+ assertNotNull(validLine.getKey());
+ assertNotNull(validLine.getValue());
+ assertEquals("key", text.substring(validLine.getKey().getOffset(), validLine.getKey().getOffset() + validLine.getKey().getLength()));
+ assertEquals("value", text.substring(validLine.getValue().getOffset(), validLine.getValue().getOffset() + validLine.getValue().getLength()));
+
+ // Test errors
+ Problem syntaxError1 = results.syntaxErrors.get(0);
+ assertEquals(11, syntaxError1.getOffset());
+ Problem syntaxError2 = results.syntaxErrors.get(1);
+ assertEquals(text.length(), syntaxError2.getOffset());
+ }
+
+}
diff --git a/vscode-extensions/commons/pom.xml b/vscode-extensions/commons/pom.xml
index 9dff83f23..fd56e653b 100644
--- a/vscode-extensions/commons/pom.xml
+++ b/vscode-extensions/commons/pom.xml
@@ -14,6 +14,7 @@
language-server-test-harness
yaml-commons
util-commons
+ java-properties