diff --git a/pom.xml b/pom.xml
index 0ba4cd48..77de9bed 100644
--- a/pom.xml
+++ b/pom.xml
@@ -6,7 +6,7 @@
net.quickwrite
fluent4j
- 0.2.0-alpha
+ 0.2.1-alpha
diff --git a/src/main/java/net/quickwrite/fluent4j/ast/FluentBase.java b/src/main/java/net/quickwrite/fluent4j/ast/FluentBase.java
index 57554c4a..d12ac430 100644
--- a/src/main/java/net/quickwrite/fluent4j/ast/FluentBase.java
+++ b/src/main/java/net/quickwrite/fluent4j/ast/FluentBase.java
@@ -1,21 +1,11 @@
package net.quickwrite.fluent4j.ast;
-import net.quickwrite.fluent4j.ast.placeable.AttributeReference;
-import net.quickwrite.fluent4j.ast.placeable.SelectExpression;
-import net.quickwrite.fluent4j.ast.placeable.TermReference;
-import net.quickwrite.fluent4j.ast.placeable.base.FluentPlaceable;
-import net.quickwrite.fluent4j.ast.placeable.base.FluentSelectable;
import net.quickwrite.fluent4j.exception.FluentParseException;
-import net.quickwrite.fluent4j.exception.FluentSelectException;
-import net.quickwrite.fluent4j.parser.FluentParser;
import net.quickwrite.fluent4j.util.StringSlice;
import net.quickwrite.fluent4j.util.StringSliceUtil;
import net.quickwrite.fluent4j.util.args.FluentArgs;
import net.quickwrite.fluent4j.util.bundle.DirectFluentBundle;
-import org.apache.commons.lang3.tuple.ImmutablePair;
-import org.apache.commons.lang3.tuple.Pair;
-import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
@@ -51,11 +41,17 @@ private List parse(final StringSlice content) {
while (!content.isBigger()) {
if (content.getChar() == '{') {
- elements.add(getPlaceable(content));
+ content.increment();
+ elements.add(StringSliceUtil.getPlaceable(content));
+
+ if (content.getChar() != '}') {
+ throw new FluentParseException('}', content.getCharUTF16(), content.getAbsolutePosition());
+ }
+ content.increment();
} else {
FluentTextElement text = getText(content, firstLine);
- if (text != null) {
+ if (text != null && !text.isEmpty()) {
elements.add(text);
}
}
@@ -88,107 +84,10 @@ private FluentTextElement getText(final StringSlice content, final boolean first
return new FluentTextElement(content.substring(start, content.getPosition()), whitespace);
}
- private FluentPlaceable getPlaceable(final StringSlice content) {
- content.increment();
- StringSliceUtil.skipWhitespaceAndNL(content);
-
- FluentPlaceable placeable = StringSliceUtil.getExpression(content);
-
- boolean canSelect = placeable instanceof FluentSelectable;
-
- StringSliceUtil.skipWhitespaceAndNL(content);
-
- if (canSelect && content.getChar() == '-') {
- content.increment();
- if (content.getChar() != '>') {
- throw new FluentParseException("->", "-" + content.getCharUTF16(), content.getAbsolutePosition());
- }
-
- content.increment();
-
- StringSliceUtil.skipWhitespaceAndNL(content);
-
- List fluentVariants = new ArrayList<>();
- FluentVariant defaultVariant = null;
-
- while (content.getChar() != '}') {
- Pair variant = getVariant(content);
-
- fluentVariants.add(variant.getLeft());
-
- if (!variant.getRight()) {
- continue;
- }
-
- if (defaultVariant != null) {
- throw new FluentSelectException("Only one variant can be marked as default (*)");
- }
-
- defaultVariant = variant.getLeft();
- }
-
- if (defaultVariant == null) {
- throw new FluentSelectException("Expected one of the variants to be marked as default (*)");
- }
-
- placeable = new SelectExpression(placeable, fluentVariants, defaultVariant);
- }
-
- StringSliceUtil.skipWhitespaceAndNL(content);
-
- if (content.getChar() != '}') {
- throw new FluentParseException('}', content.getCharUTF16(), content.getAbsolutePosition());
- }
-
- content.increment();
-
- return placeable;
- }
-
public String getIdentifier() {
return this.identifier;
}
- private Pair getVariant(final StringSlice content) {
- StringSliceUtil.skipWhitespaceAndNL(content);
-
- boolean isDefault = false;
-
- if (content.getChar() == '*') {
- isDefault = true;
- content.increment();
- }
-
- if (content.getChar() != '[') {
- throw new FluentParseException('[', content.getCharUTF16(), content.getAbsolutePosition());
- }
-
- content.increment();
-
- StringSliceUtil.skipWhitespace(content);
-
- StringSlice identifier = getVariantIdentifier(content);
-
- StringSliceUtil.skipWhitespace(content);
-
- if (content.getChar() != ']') {
- throw getVariantException(content, identifier.toString(), "]");
- }
-
- content.increment();
-
- final Pair stringSliceContent = FluentParser.getMessageContent(content,
- character -> character == '[' || character == '*' || character == '}');
-
- final FluentAttribute attribute = new FluentAttribute(
- identifier,
- stringSliceContent.getLeft(),
- stringSliceContent.getRight()
- );
-
- return new ImmutablePair<>(new FluentVariant(attribute), isDefault);
- }
-
private StringSlice getVariantIdentifier(final StringSlice content) {
char character = content.getChar();
final int start = content.getPosition();
@@ -238,16 +137,4 @@ public String stringValue() {
public List getElements() {
return this.fluentElements;
}
-
- private FluentParseException getVariantException(final StringSlice content, final String prev, final String expected) {
- int start = content.getPosition();
-
- while (content.getChar() != ']' && !content.isBigger()) {
- content.increment();
- }
-
- return new FluentParseException(expected,
- prev + content.substring(start, content.getPosition()).toString(),
- content.getAbsolutePosition());
- }
}
diff --git a/src/main/java/net/quickwrite/fluent4j/ast/FluentTextElement.java b/src/main/java/net/quickwrite/fluent4j/ast/FluentTextElement.java
index 025df9f2..6fcae2f0 100644
--- a/src/main/java/net/quickwrite/fluent4j/ast/FluentTextElement.java
+++ b/src/main/java/net/quickwrite/fluent4j/ast/FluentTextElement.java
@@ -67,6 +67,10 @@ private String getText(final StringSlice content, final int whitespace) {
return text.toString();
}
+ public boolean isEmpty() {
+ return text.isEmpty();
+ }
+
@Override
public boolean matches(final DirectFluentBundle bundle, final FluentElement selector) {
return selector.stringValue().equals(this.text);
diff --git a/src/main/java/net/quickwrite/fluent4j/ast/FluentVariant.java b/src/main/java/net/quickwrite/fluent4j/ast/FluentVariant.java
index a3873e0d..be73cabe 100644
--- a/src/main/java/net/quickwrite/fluent4j/ast/FluentVariant.java
+++ b/src/main/java/net/quickwrite/fluent4j/ast/FluentVariant.java
@@ -1,5 +1,6 @@
package net.quickwrite.fluent4j.ast;
+import net.quickwrite.fluent4j.exception.FluentParseException;
import net.quickwrite.fluent4j.util.args.FluentArgs;
import net.quickwrite.fluent4j.util.bundle.DirectFluentBundle;
import net.quickwrite.fluent4j.ast.placeable.NumberLiteral;
@@ -21,14 +22,18 @@ public class FluentVariant implements FluentElement {
private final FluentPlaceable identifier;
private final FluentAttribute content;
- public FluentVariant(FluentAttribute content) {
+ public FluentVariant(final FluentAttribute content) {
this.identifier = getIdentifier(content.identifier);
this.content = content;
}
- private FluentPlaceable getIdentifier(String slice) {
+ private FluentPlaceable getIdentifier(final String slice) {
if (Character.isDigit(slice.charAt(0))) {
- return NumberLiteral.getNumberLiteral(slice);
+ try {
+ return NumberLiteral.getNumberLiteral(slice);
+ } catch (final NumberFormatException ignored) {
+ throw new FluentParseException("Expected Number but got \"" + slice + "\"");
+ }
}
return new StringLiteral(slice);
diff --git a/src/main/java/net/quickwrite/fluent4j/ast/placeable/AttributeReference.java b/src/main/java/net/quickwrite/fluent4j/ast/placeable/AttributeReference.java
index a44b361d..4652fbfb 100644
--- a/src/main/java/net/quickwrite/fluent4j/ast/placeable/AttributeReference.java
+++ b/src/main/java/net/quickwrite/fluent4j/ast/placeable/AttributeReference.java
@@ -53,14 +53,19 @@ public CharSequence getResult(final DirectFluentBundle bundle, final FluentArgs
return getErrorString();
}
- return attribute.getResult(bundle, arguments);
+ return attribute.getResult(bundle, getArguments(arguments));
}
@Override
public FluentElement getArgumentResult(final DirectFluentBundle bundle, final FluentArgs arguments) {
- final FluentAttribute attribute = this.getMessage(bundle, reference.stringValue())
- .getAttribute(this.attributeIdentifier);
- if (attribute == null) {
+ final FluentMessage fluentMessage = this.getMessage(bundle, reference.stringValue());
+ if (fluentMessage == null) {
+ return this;
+ }
+
+ final FluentAttribute attribute = fluentMessage.getAttribute(this.attributeIdentifier);
+
+ if(attribute == null) {
return this;
}
@@ -71,7 +76,7 @@ public FluentElement getArgumentResult(final DirectFluentBundle bundle, final Fl
}
// No recursion (unfortunately :d)
- return (FluentElement) elementList.get(0);
+ return elementList.get(0);
}
protected FluentMessage getMessage(final DirectFluentBundle bundle, final String key) {
@@ -82,6 +87,10 @@ protected String getErrorString() {
return "{" + reference.stringValue() + "." + attributeIdentifier + "}";
}
+ protected FluentArgs getArguments(final FluentArgs defaultArgs) {
+ return defaultArgs;
+ }
+
@Override
public String toString() {
return "FluentAttributeReference: {\n" +
@@ -91,8 +100,12 @@ public String toString() {
}
public static class TermAttributeReference extends AttributeReference implements FluentSelectable {
- public TermAttributeReference(FluentPlaceable reference, StringSlice content) {
+ private final FluentArgs arguments;
+
+ public TermAttributeReference(final FluentPlaceable reference, final StringSlice content, final FluentArgs arguments) {
super(reference, content);
+
+ this.arguments = arguments;
}
@Override
@@ -104,5 +117,19 @@ protected FluentMessage getMessage(final DirectFluentBundle bundle, final String
protected String getErrorString() {
return "{-" + reference.stringValue() + "." + attributeIdentifier + "}";
}
+
+ @Override
+ protected FluentArgs getArguments(final FluentArgs defaultArgs) {
+ return this.arguments;
+ }
+
+ @Override
+ public String toString() {
+ return "FluentTermAttributeReference: {\n" +
+ "\t\t\tvalue: \"" + this.reference + "\"\n" +
+ "\t\t\tattribute: \"" + this.attributeIdentifier + "\"\n" +
+ "\t\t\targuments: \"" + this.arguments + "\"\n" +
+ "\t\t}";
+ }
}
}
\ No newline at end of file
diff --git a/src/main/java/net/quickwrite/fluent4j/ast/placeable/FunctionReference.java b/src/main/java/net/quickwrite/fluent4j/ast/placeable/FunctionReference.java
index a42d4ba7..425b067d 100644
--- a/src/main/java/net/quickwrite/fluent4j/ast/placeable/FunctionReference.java
+++ b/src/main/java/net/quickwrite/fluent4j/ast/placeable/FunctionReference.java
@@ -16,8 +16,8 @@
*/
public class FunctionReference extends FluentFunction implements FluentSelectable {
- public FunctionReference(final String functionName, final StringSlice content) {
- super(functionName, content);
+ public FunctionReference(final String functionName, final FluentArgs arguments) {
+ super(functionName, arguments);
}
@Override
diff --git a/src/main/java/net/quickwrite/fluent4j/ast/placeable/TermReference.java b/src/main/java/net/quickwrite/fluent4j/ast/placeable/TermReference.java
index ec34c9f9..d3cad0c5 100644
--- a/src/main/java/net/quickwrite/fluent4j/ast/placeable/TermReference.java
+++ b/src/main/java/net/quickwrite/fluent4j/ast/placeable/TermReference.java
@@ -5,7 +5,6 @@
import net.quickwrite.fluent4j.ast.placeable.base.FluentFunction;
import net.quickwrite.fluent4j.util.StringSlice;
import net.quickwrite.fluent4j.util.args.FluentArgs;
-import net.quickwrite.fluent4j.util.args.FluentArguments;
import net.quickwrite.fluent4j.util.bundle.DirectFluentBundle;
/**
@@ -30,8 +29,8 @@ public TermReference(final StringSlice name) {
super(name, null);
}
- public TermReference(final String name, final StringSlice content) {
- super(name, content);
+ public TermReference(final String name, final FluentArgs arguments) {
+ super(name, arguments);
}
@Override
@@ -60,11 +59,6 @@ public FluentElement getArgumentResult(final DirectFluentBundle bundle, final Fl
return term;
}
- @Override
- protected FluentArgs getFluentArgumentInstance() {
- return new FluentArguments();
- }
-
@Override
public String toString() {
return "FluentTermReference: {\n" +
diff --git a/src/main/java/net/quickwrite/fluent4j/ast/placeable/base/FluentFunction.java b/src/main/java/net/quickwrite/fluent4j/ast/placeable/base/FluentFunction.java
index 056f3789..9b1b15c9 100644
--- a/src/main/java/net/quickwrite/fluent4j/ast/placeable/base/FluentFunction.java
+++ b/src/main/java/net/quickwrite/fluent4j/ast/placeable/base/FluentFunction.java
@@ -3,13 +3,9 @@
import net.quickwrite.fluent4j.ast.FluentElement;
import net.quickwrite.fluent4j.exception.FluentParseException;
import net.quickwrite.fluent4j.util.StringSlice;
-import net.quickwrite.fluent4j.util.StringSliceUtil;
import net.quickwrite.fluent4j.util.args.FluentArgs;
-import net.quickwrite.fluent4j.util.args.FunctionFluentArgs;
import net.quickwrite.fluent4j.util.args.FunctionFluentArguments;
import net.quickwrite.fluent4j.util.bundle.DirectFluentBundle;
-import org.apache.commons.lang3.tuple.ImmutablePair;
-import org.apache.commons.lang3.tuple.Pair;
/**
* Implements the basis for a value that gets
@@ -20,68 +16,18 @@ public abstract class FluentFunction implements FluentPlaceable, FluentArgumentR
protected final String functionName;
protected final FluentArgs arguments;
- public FluentFunction(final StringSlice functionName, final StringSlice content) {
- this(functionName.toString(), content);
+ public FluentFunction(final StringSlice functionName, final FluentArgs arguments) {
+ this(functionName.toString(), arguments);
}
- public FluentFunction(final String functionName, final StringSlice content) {
+ public FluentFunction(final String functionName, final FluentArgs arguments) {
this.functionName = functionName;
if (!check(functionName)) {
// TODO: Better Error handling
throw new FluentParseException("The callee has to be an upper-case identifier or a term");
}
- this.arguments = (content == null) ? FunctionFluentArgs.EMPTY_ARGS : this.getArguments(content);
- }
-
- private FluentArgs getArguments(final StringSlice content) {
- StringSliceUtil.skipWhitespaceAndNL(content);
- if (content.isBigger()) {
- return FunctionFluentArgs.EMPTY_ARGS;
- }
-
- final FunctionFluentArgs arguments = (FunctionFluentArgs) this.getFluentArgumentInstance();
-
- while (!content.isBigger()) {
- Pair argument = getArgument(content);
- if (argument.getLeft() != null) {
- arguments.setNamed(argument.getLeft(), argument.getRight());
- } else {
- arguments.addPositional(argument.getRight());
- }
-
- StringSliceUtil.skipWhitespaceAndNL(content);
-
- if (content.getChar() != ',') {
- if (!content.isBigger()) {
- throw new FluentParseException("','", content.getCharUTF16(), content.getAbsolutePosition());
- }
- break;
- }
- content.increment();
-
- StringSliceUtil.skipWhitespaceAndNL(content);
- }
-
- return arguments;
- }
-
- private Pair getArgument(final StringSlice content) {
- FluentPlaceable placeable = StringSliceUtil.getExpression(content);
- String identifier = null;
-
- StringSliceUtil.skipWhitespaceAndNL(content);
-
- if (content.getChar() == ':') {
- content.increment();
- StringSliceUtil.skipWhitespaceAndNL(content);
-
- identifier = placeable.stringValue();
-
- placeable = StringSliceUtil.getExpression(content);
- }
-
- return new ImmutablePair<>(identifier, placeable);
+ this.arguments = arguments != null ? arguments : FluentArgs.EMPTY_ARGS;
}
/**
@@ -93,12 +39,10 @@ private Pair getArgument(final StringSlice content) {
* @return The sanitized arguments of the function
*/
protected FluentArgs getArguments(final DirectFluentBundle bundle, final FluentArgs arguments) {
- this.arguments.sanitize(bundle, arguments);
- return this.arguments;
- }
+ if (this.arguments != null)
+ this.arguments.sanitize(bundle, arguments);
- protected FluentArgs getFluentArgumentInstance() {
- return new FunctionFluentArguments();
+ return this.arguments;
}
/**
diff --git a/src/main/java/net/quickwrite/fluent4j/parser/FluentParser.java b/src/main/java/net/quickwrite/fluent4j/parser/FluentParser.java
index 6c6900bd..5e8f717d 100644
--- a/src/main/java/net/quickwrite/fluent4j/parser/FluentParser.java
+++ b/src/main/java/net/quickwrite/fluent4j/parser/FluentParser.java
@@ -1,17 +1,18 @@
package net.quickwrite.fluent4j.parser;
-import net.quickwrite.fluent4j.util.bundle.FluentResource;
-import net.quickwrite.fluent4j.util.bundle.SimpleFluentResource;
import net.quickwrite.fluent4j.ast.*;
import net.quickwrite.fluent4j.exception.FluentParseException;
import net.quickwrite.fluent4j.util.StringSlice;
import net.quickwrite.fluent4j.util.StringSliceUtil;
+import net.quickwrite.fluent4j.util.bundle.FluentResource;
+import net.quickwrite.fluent4j.util.bundle.SimpleFluentResource;
import org.apache.commons.lang3.tuple.ImmutablePair;
import org.apache.commons.lang3.tuple.Pair;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
+import java.util.regex.Pattern;
/**
* Parses a String into a FluentResource so that it can be queried.
@@ -30,20 +31,20 @@ public abstract class FluentParser {
*
* @return FluentResource
*/
- public static FluentResource parse(final String content) {
- final StringSlice input = convertString(content);
+ public static FluentResource parse(final String input) {
+ final StringSlice content = convertString(input);
List elementList = new ArrayList<>();
List exceptionList = new LinkedList<>();
- while (input.length() >= input.length()) {
- if (input.getChar() == '#') {
- handleComment(input);
+ while (content.length() >= content.length()) {
+ if (content.getChar() == '#') {
+ handleComment(content);
continue;
}
try {
- FluentBase fluentBase = getBase(input);
+ FluentBase fluentBase = getBase(content);
if (fluentBase != null) {
elementList.add(fluentBase);
@@ -54,48 +55,48 @@ public static FluentResource parse(final String content) {
continue;
}
- int startSkip = input.getPosition();
- StringSliceUtil.skipWhitespaceAndNL(input);
+ int startSkip = content.getPosition();
+ StringSliceUtil.skipWhitespaceAndNL(content);
- if (startSkip == input.getPosition()) {
- if (input.getChar() == '\n' || input.getChar() == ' ' || input.getChar() == '\0') {
+ if (startSkip == content.getPosition()) {
+ if (content.getChar() == '\n' || content.getChar() == ' ' || content.getChar() == '\0') {
break;
}
- exceptionList.add(new FluentParseException("an entry start", input.getCharUTF16(), input.getPosition()));
+ exceptionList.add(new FluentParseException("an entry start", content.getCharUTF16(), content.getPosition()));
- while (input.getChar() != '\n' && !input.isBigger()) {
- input.increment();
+ while (content.getChar() != '\n' && !content.isBigger()) {
+ content.increment();
}
}
}
- input.setIndex(0);
+ content.setIndex(0);
return new SimpleFluentResource(elementList, exceptionList);
}
- private static FluentBase getBase(final StringSlice input) {
+ private static FluentBase getBase(final StringSlice content) {
boolean isIdentifier = false;
- if (input.getChar() == '-') {
- input.increment();
+ if (content.getChar() == '-') {
+ content.increment();
isIdentifier = true;
- } else if (!Character.isAlphabetic(input.getChar())) {
+ } else if (!Character.isAlphabetic(content.getChar())) {
return null;
}
- StringSlice identifier = StringSliceUtil.getIdentifier(input);
+ StringSlice identifier = StringSliceUtil.getIdentifier(content);
- StringSliceUtil.skipWhitespace(input);
+ StringSliceUtil.skipWhitespace(content);
- if (input.getChar() != '=') {
- throw new FluentParseException('=', input.getCharUTF16(), input.getAbsolutePosition());
+ if (content.getChar() != '=') {
+ throw new FluentParseException('=', content.getCharUTF16(), content.getAbsolutePosition());
}
- input.increment();
+ content.increment();
- final Pair, List> pair = getContent(input);
+ final Pair, List> pair = getContent(content);
if (!isIdentifier) {
// must be a Message
@@ -106,9 +107,9 @@ private static FluentBase getBase(final StringSlice input) {
}
}
- private static void handleComment(final StringSlice input) {
- while (input.getChar() != '\n' && input.getChar() != '\0') {
- input.increment();
+ private static void handleComment(final StringSlice content) {
+ while (content.getChar() != '\n' && content.getChar() != '\0') {
+ content.increment();
}
}
@@ -136,98 +137,59 @@ private static Pair, List> getConten
return new ImmutablePair<>(content, attributes);
}
- private static Pair getMessageContent(final StringSlice input) {
- return getMessageContent(input, character -> character == '.');
+ private static Pair getMessageContent(final StringSlice content) {
+ return getMessageContent(content, character -> character == '.');
}
- public static Pair getMessageContent(final StringSlice input, final BreakChecker breaker) {
- StringSliceUtil.skipWhitespace(input);
- final int start = input.getPosition();
+ public static Pair getMessageContent(final StringSlice content, final BreakChecker breaker) {
+ StringSliceUtil.skipWhitespace(content);
+ final int start = content.getPosition();
int lastWhitespace = start;
boolean first = true;
int leadingWhitespace = Integer.MAX_VALUE;
do {
- int whitespace = StringSliceUtil.skipWhitespace(input);
- if (!first && whitespace < leadingWhitespace && whitespace != 0) {
- leadingWhitespace = whitespace;
+ int whitespace = StringSliceUtil.skipWhitespace(content);
+ if (!first && breaker.isEndCharacter(content.getChar())) {
+ break;
}
- if (!first && breaker.isEndCharacter(input.getChar())) {
- break;
+ if (!first && whitespace < leadingWhitespace && whitespace != 0) {
+ leadingWhitespace = whitespace;
}
first = false;
- while (input.getChar() != '\n' && input.getChar() != '\0') {
- if (input.getChar() == '{') {
- skipPlaceable(input);
+ while (content.getChar() != '\n' && content.getChar() != '\0') {
+ if (content.getChar() == '{') {
+ content.increment();
+ StringSliceUtil.getPlaceable(content);
}
- if (input.getChar() != ' ') {
- lastWhitespace = input.getPosition();
+ if (content.getChar() != ' ') {
+ lastWhitespace = content.getPosition();
}
- input.increment();
+ content.increment();
}
- input.increment();
- } while (input.getChar() == ' ' || input.getChar() == '\n');
+ content.increment();
+ } while (content.getChar() == ' ' || content.getChar() == '\n');
if (leadingWhitespace == Integer.MAX_VALUE) {
leadingWhitespace = 0;
}
- return new ImmutablePair<>(input.substring(start, lastWhitespace + 1), leadingWhitespace);
+ return new ImmutablePair<>(content.substring(start, lastWhitespace + 1), leadingWhitespace);
}
- private static void skipPlaceable(final StringSlice input) {
- input.increment();
-
- int openCurly = 1;
- boolean justWhitespace = true;
-
- while (!input.isBigger()) {
- char character = input.getChar();
+ private final static Pattern stringConverter;
- switch (character) {
- case '"':
- if (!justWhitespace) break;
-
- character = input.getChar();
- input.increment();
-
- while (!(input.getChar() == '"' && character != '\\') && input.getChar() != '\n' && !input.isBigger()) {
- character = input.getChar();
- input.increment();
- }
-
- break;
- case '{':
- openCurly++;
-
- justWhitespace = true;
-
- break;
- case '}':
- openCurly--;
-
- if (openCurly == 0) {
- return;
- }
-
- break;
- default:
- if (!Character.isWhitespace(character)) {
- justWhitespace = false;
- }
- }
-
- input.increment();
- }
+ static {
+ stringConverter = Pattern.compile("(\\r\\n|\\r|\\f)");
}
private static StringSlice convertString(final String input) {
- return new StringSlice(input.replace("\r", ""));
+ return new StringSlice(stringConverter.matcher(input).replaceAll("\n"));
}
/**
diff --git a/src/main/java/net/quickwrite/fluent4j/util/StringSliceUtil.java b/src/main/java/net/quickwrite/fluent4j/util/StringSliceUtil.java
index dbb49274..11f1b674 100644
--- a/src/main/java/net/quickwrite/fluent4j/util/StringSliceUtil.java
+++ b/src/main/java/net/quickwrite/fluent4j/util/StringSliceUtil.java
@@ -1,8 +1,22 @@
package net.quickwrite.fluent4j.util;
+import net.quickwrite.fluent4j.ast.FluentAttribute;
+import net.quickwrite.fluent4j.ast.FluentElement;
+import net.quickwrite.fluent4j.ast.FluentVariant;
import net.quickwrite.fluent4j.ast.placeable.*;
import net.quickwrite.fluent4j.ast.placeable.base.FluentPlaceable;
+import net.quickwrite.fluent4j.ast.placeable.base.FluentSelectable;
import net.quickwrite.fluent4j.exception.FluentParseException;
+import net.quickwrite.fluent4j.exception.FluentSelectException;
+import net.quickwrite.fluent4j.parser.FluentParser;
+import net.quickwrite.fluent4j.util.args.FluentArgs;
+import net.quickwrite.fluent4j.util.args.FunctionFluentArgs;
+import net.quickwrite.fluent4j.util.args.FunctionFluentArguments;
+import org.apache.commons.lang3.tuple.ImmutablePair;
+import org.apache.commons.lang3.tuple.Pair;
+
+import java.util.ArrayList;
+import java.util.List;
/**
* A collection of different utility methods
@@ -120,12 +134,7 @@ public static FluentPlaceable getExpression(final StringSlice slice) {
case '"' -> {
slice.increment();
final int start = slice.getPosition();
- while (!(slice.getChar() == '"' || slice.getChar() == '\n') && !slice.isBigger()) {
- if (slice.getChar() == '\\' && slice.peek(1) == '"')
- slice.increment();
-
- slice.increment();
- }
+ skipStringLiteral(slice);
if (slice.getChar() != '"') {
slice.decrement(2);
@@ -147,6 +156,16 @@ public static FluentPlaceable getExpression(final StringSlice slice) {
return expression;
}
+ public static void skipStringLiteral(final StringSlice slice) {
+ while (!(slice.getChar() == '"' || slice.getChar() == '\n') && !slice.isBigger()) {
+ final char peek = slice.peek(1);
+ if (slice.getChar() == '\\' && (peek == '"' || peek == '\\'))
+ slice.increment();
+
+ slice.increment();
+ }
+ }
+
private static FluentPlaceable expressionGetDefault(final StringSlice slice) {
boolean isTerm = false;
@@ -160,7 +179,12 @@ private static FluentPlaceable expressionGetDefault(final StringSlice slice) {
if (isTerm)
slice.decrement();
- return NumberLiteral.getNumberLiteral(getNumber(slice));
+ final StringSlice number = getNumber(slice);
+ try {
+ return NumberLiteral.getNumberLiteral(number);
+ } catch (final NumberFormatException ignored) {
+ throw new FluentParseException("Number", number.toString(), number.getPosition() - number.length());
+ }
}
final StringSlice msgIdentifier = getIdentifier(slice);
@@ -180,34 +204,14 @@ private static FluentPlaceable expressionGetDefault(final StringSlice slice) {
private static FluentPlaceable expressionGetFunction(final StringSlice slice, FluentPlaceable expression, final boolean isTerm) {
slice.increment();
- int start = slice.getPosition();
-
- int open = 0;
-
- while (!(slice.getChar() == ')' && open == 0)) {
- if (slice.isBigger()) {
- throw new FluentParseException(")", "EOF", slice.getAbsolutePosition());
- }
-
- if (slice.getChar() == '(') {
- open++;
- }
-
- if (slice.getChar() == ')') {
- open--;
- }
-
- slice.increment();
- }
-
expression = (!isTerm) ?
new FunctionReference(
expression.stringValue(),
- slice.substring(start, slice.getPosition())
+ parseArguments(slice)
) :
new TermReference(
expression.stringValue(),
- slice.substring(start, slice.getPosition())
+ parseArguments(slice)
);
slice.increment();
@@ -220,7 +224,15 @@ private static FluentPlaceable expressionGetAttribute(final StringSlice slice, F
final StringSlice identifier = StringSliceUtil.getIdentifier(slice);
if (isTerm) {
- expression = new AttributeReference.TermAttributeReference(expression, identifier);
+ skipWhitespaceAndNL(slice);
+ FluentArgs arguments = null;
+
+ if (slice.getChar() == '(') {
+ slice.increment();
+ arguments = parseArguments(slice);
+ slice.increment();
+ }
+ expression = new AttributeReference.TermAttributeReference(expression, identifier, arguments);
} else {
expression = new AttributeReference(expression, identifier);
}
@@ -228,6 +240,102 @@ private static FluentPlaceable expressionGetAttribute(final StringSlice slice, F
return expression;
}
+ /**
+ * Returns a simple {@link FluentArgs} object that
+ * contains the arguments that can be created in the
+ * {@code .ftl}-files.
+ *
+ *
+ * The arguments are always in a format
+ * of being in {@code ()} and being separated
+ * by {@code ,}.
+ *
+ *
+ * There are two different types of arguments:
+ *
+ * -
+ * Positional Arguments:
+ *
+ * Arguments that don't have a name and
+ * are just denominated by their position in the
+ * arguments.
+ *
+ * -
+ * Named Arguments:
+ *
+ * Arguments that have a name that is being
+ * declared in front of the argument by
+ * having a {@code :} as a separator.
+ *
+ * This means that to create a named argument
+ * the argument is created by having this format:
+ * {{name}} : {{argument}}
+ *
+ * They can only be accessed by their name as
+ * the key.
+ *
+ *
+ *
+ *
+ * If there are no arguments in the brackets
+ * the function will return {@link FluentArgs#EMPTY_ARGS}.
+ *
+ *
+ * @param content The content the arguments are in
+ * @return The arguments as an option
+ */
+ private static FluentArgs parseArguments(final StringSlice content) {
+ if (content == null) {
+ return FluentArgs.EMPTY_ARGS;
+ }
+
+ StringSliceUtil.skipWhitespaceAndNL(content);
+ if (content.isBigger()) {
+ return FunctionFluentArgs.EMPTY_ARGS;
+ }
+
+ final FunctionFluentArgs arguments = new FunctionFluentArguments();
+
+ while (!content.isBigger() && content.getChar() != ')') {
+ Pair argument = getArgument(content);
+
+ if (argument.getLeft() != null) {
+ arguments.setNamed(argument.getLeft(), argument.getRight());
+ } else {
+ arguments.addPositional(argument.getRight());
+ }
+
+ StringSliceUtil.skipWhitespaceAndNL(content);
+
+ if (content.getChar() != ',') {
+ break;
+ }
+ content.increment();
+
+ StringSliceUtil.skipWhitespaceAndNL(content);
+ }
+
+ return arguments;
+ }
+
+ private static Pair getArgument(final StringSlice content) {
+ FluentPlaceable placeable = StringSliceUtil.getExpression(content);
+ String identifier = null;
+
+ StringSliceUtil.skipWhitespaceAndNL(content);
+
+ if (content.getChar() == ':') {
+ content.increment();
+ StringSliceUtil.skipWhitespaceAndNL(content);
+
+ identifier = placeable.stringValue();
+
+ placeable = StringSliceUtil.getExpression(content);
+ }
+
+ return new ImmutablePair<>(identifier, placeable);
+ }
+
private static StringSlice getNumber(final StringSlice slice) {
char character = slice.getChar();
final int start = slice.getPosition();
@@ -271,4 +379,134 @@ public static StringSlice getIdentifier(final StringSlice slice) {
return slice.substring(start, slice.getPosition());
}
+
+ /**
+ * Returns the parsed version of the {@link FluentPlaceable}
+ * that is inside the {}
.
+ *
+ *
+ * This can either be a simple expression or
+ * a complete {@link SelectExpression}.
+ *
+ *
+ * @param content The content that the placeable currently is at
+ * @return The Placeable
+ */
+ public static FluentPlaceable getPlaceable(final StringSlice content) {
+ StringSliceUtil.skipWhitespaceAndNL(content);
+
+ FluentPlaceable placeable = StringSliceUtil.getExpression(content);
+
+ boolean canSelect = placeable instanceof FluentSelectable;
+
+ StringSliceUtil.skipWhitespaceAndNL(content);
+
+ if (canSelect && content.getChar() == '-') {
+ content.increment();
+ if (content.getChar() != '>') {
+ throw new FluentParseException("->", "-" + content.getCharUTF16(), content.getAbsolutePosition());
+ }
+
+ content.increment();
+
+ StringSliceUtil.skipWhitespaceAndNL(content);
+
+ final List fluentVariants = new ArrayList<>();
+ FluentVariant defaultVariant = null;
+
+ while (content.getChar() != '}') {
+ final Pair variant = getVariant(content);
+
+ fluentVariants.add(variant.getLeft());
+
+ if (!variant.getRight()) {
+ continue;
+ }
+
+ if (defaultVariant != null) {
+ throw new FluentSelectException("Only one variant can be marked as default (*)");
+ }
+
+ defaultVariant = variant.getLeft();
+ }
+
+ if (defaultVariant == null) {
+ throw new FluentSelectException("Expected one of the variants to be marked as default (*)");
+ }
+
+ placeable = new SelectExpression(placeable, fluentVariants, defaultVariant);
+ }
+
+ StringSliceUtil.skipWhitespaceAndNL(content);
+
+ return placeable;
+ }
+
+ private static Pair getVariant(final StringSlice content) {
+ StringSliceUtil.skipWhitespaceAndNL(content);
+
+ boolean isDefault = false;
+
+ if (content.getChar() == '*') {
+ isDefault = true;
+ content.increment();
+ }
+
+ if (content.getChar() != '[') {
+ throw new FluentParseException('[', content.getCharUTF16(), content.getAbsolutePosition());
+ }
+
+ content.increment();
+
+ StringSliceUtil.skipWhitespace(content);
+
+ final StringSlice identifier = getVariantIdentifier(content);
+
+ StringSliceUtil.skipWhitespace(content);
+
+ if (content.getChar() != ']') {
+ throw getVariantException(content, identifier.toString(), "]");
+ }
+
+ content.increment();
+
+ final Pair stringSliceContent = FluentParser.getMessageContent(content,
+ character -> character == '[' || character == '*' || character == '}');
+
+ final FluentAttribute attribute = new FluentAttribute(
+ identifier,
+ stringSliceContent.getLeft(),
+ stringSliceContent.getRight()
+ );
+
+ return new ImmutablePair<>(new FluentVariant(attribute), isDefault);
+ }
+
+ private static StringSlice getVariantIdentifier(final StringSlice content) {
+ char character = content.getChar();
+ final int start = content.getPosition();
+
+ while (character != ' '
+ && character != '\n'
+ && character != ']'
+ && character != '\0'
+ ) {
+ content.increment();
+ character = content.getChar();
+ }
+
+ return content.substring(start, content.getPosition());
+ }
+
+ private static FluentParseException getVariantException(final StringSlice content, final String prev, final String expected) {
+ int start = content.getPosition();
+
+ while (content.getChar() != ']' && !content.isBigger()) {
+ content.increment();
+ }
+
+ return new FluentParseException(expected,
+ prev + content.substring(start, content.getPosition()).toString(),
+ content.getAbsolutePosition());
+ }
}
diff --git a/src/main/java/net/quickwrite/fluent4j/util/bundle/ResourceFluentBundle.java b/src/main/java/net/quickwrite/fluent4j/util/bundle/ResourceFluentBundle.java
index 934377b0..c441530c 100644
--- a/src/main/java/net/quickwrite/fluent4j/util/bundle/ResourceFluentBundle.java
+++ b/src/main/java/net/quickwrite/fluent4j/util/bundle/ResourceFluentBundle.java
@@ -128,4 +128,15 @@ public boolean hasExceptions() {
public List getExceptionList() {
return this.exceptionList;
}
+
+ @Override
+ public String toString() {
+ return "ResourceFluentBundle: {\n" +
+ "\tlocale: " + this.locale + "\n" +
+ "\tterms: [\n\t\t" + this.terms + "\n\t]\n" +
+ "\tmessages: [\n\t\t" + this.messages + "\n\t]\n" +
+ "\tfunctions: [\n\t\t" + this.functions + "\n\t]\n" +
+ "\texceptions: [\n\t\t" + this.exceptionList + "\n\t]\n" +
+ "}";
+ }
}
diff --git a/src/test/java/net/quickwrite/fluent4j/TestCR.java b/src/test/java/net/quickwrite/fluent4j/TestCR.java
new file mode 100644
index 00000000..566211e6
--- /dev/null
+++ b/src/test/java/net/quickwrite/fluent4j/TestCR.java
@@ -0,0 +1,32 @@
+package net.quickwrite.fluent4j;
+
+import net.quickwrite.fluent4j.util.bundle.FluentBundle;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.jupiter.api.Assertions;
+
+import java.io.IOException;
+
+public class TestCR {
+ private FluentBundle bundle;
+
+ @Before
+ public void setUp() throws IOException {
+ this.bundle = GetFileHelper.getFluentBundle("cr.ftl");
+ }
+
+ @Test
+ public void testErr01() {
+ Assertions.assertEquals("Value 01", GetFileHelper.getMessage(bundle, "err01"));
+ }
+
+ @Test
+ public void testErr02() {
+ Assertions.assertEquals("Value 02", GetFileHelper.getMessage(bundle, "err02"));
+ }
+
+ @Test
+ public void testErr03() {
+ Assertions.assertEquals("Value 03\nContinued", GetFileHelper.getMessage(bundle, "err03"));
+ }
+}
diff --git a/src/test/java/net/quickwrite/fluent4j/TestCRLF.java b/src/test/java/net/quickwrite/fluent4j/TestCRLF.java
new file mode 100644
index 00000000..90bea297
--- /dev/null
+++ b/src/test/java/net/quickwrite/fluent4j/TestCRLF.java
@@ -0,0 +1,27 @@
+package net.quickwrite.fluent4j;
+
+import net.quickwrite.fluent4j.util.bundle.FluentBundle;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.jupiter.api.Assertions;
+
+import java.io.IOException;
+
+public class TestCRLF {
+ private FluentBundle bundle;
+
+ @Before
+ public void setUp() throws IOException {
+ this.bundle = GetFileHelper.getFluentBundle("crlf.ftl");
+ }
+
+ @Test
+ public void testKey01() {
+ Assertions.assertEquals("Value 01", GetFileHelper.getMessage(bundle, "key01"));
+ }
+
+ @Test
+ public void testKey02() {
+ Assertions.assertEquals("Value 02\nContinued", GetFileHelper.getMessage(bundle, "key02"));
+ }
+}
diff --git a/src/test/java/net/quickwrite/fluent4j/TestCallExpressions.java b/src/test/java/net/quickwrite/fluent4j/TestCallExpressions.java
index ccd25db8..31fb025c 100644
--- a/src/test/java/net/quickwrite/fluent4j/TestCallExpressions.java
+++ b/src/test/java/net/quickwrite/fluent4j/TestCallExpressions.java
@@ -3,7 +3,6 @@
import net.quickwrite.fluent4j.ast.placeable.StringLiteral;
import net.quickwrite.fluent4j.ast.placeable.base.FluentPlaceable;
import net.quickwrite.fluent4j.functions.AbstractFunction;
-import net.quickwrite.fluent4j.util.args.FluentArgs;
import net.quickwrite.fluent4j.util.args.FunctionFluentArgs;
import net.quickwrite.fluent4j.util.bundle.DirectFluentBundle;
import net.quickwrite.fluent4j.util.bundle.FluentBundle;
diff --git a/src/test/java/net/quickwrite/fluent4j/TestCalleeExpressions.java b/src/test/java/net/quickwrite/fluent4j/TestCalleeExpressions.java
new file mode 100644
index 00000000..7a7fab34
--- /dev/null
+++ b/src/test/java/net/quickwrite/fluent4j/TestCalleeExpressions.java
@@ -0,0 +1,42 @@
+package net.quickwrite.fluent4j;
+
+import net.quickwrite.fluent4j.util.bundle.FluentBundle;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.io.IOException;
+
+public class TestCalleeExpressions {
+ private FluentBundle bundle;
+
+ @Before
+ public void setUp() throws IOException {
+ this.bundle = GetFileHelper.getFluentBundle("callee_expressions.ftl");
+ }
+
+ @Test
+ public void testIfExceptions() {
+ Assert.assertTrue(bundle.hasExceptions());
+ }
+
+ @Test
+ public void testFunctionCalleePlaceable() {
+ Assert.assertEquals("{FUNCTION()}", GetFileHelper.getMessage(bundle, "function-callee-placeable"));
+ }
+
+ @Test
+ public void testTermCalleePlaceable() {
+ Assert.assertEquals("{-term}", GetFileHelper.getMessage(bundle, "term-callee-placeable"));
+ }
+
+ @Test
+ public void testFunctionCalleeSelector() {
+ Assert.assertEquals("Value", GetFileHelper.getMessage(bundle, "function-callee-selector"));
+ }
+
+ @Test
+ public void testTermAttrCalleeSelector() {
+ Assert.assertEquals("Value", GetFileHelper.getMessage(bundle, "term-attr-callee-selector"));
+ }
+}
diff --git a/src/test/java/net/quickwrite/fluent4j/TestComments.java b/src/test/java/net/quickwrite/fluent4j/TestComments.java
new file mode 100644
index 00000000..6d512441
--- /dev/null
+++ b/src/test/java/net/quickwrite/fluent4j/TestComments.java
@@ -0,0 +1,27 @@
+package net.quickwrite.fluent4j;
+
+import net.quickwrite.fluent4j.util.bundle.FluentBundle;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.jupiter.api.Assertions;
+
+import java.io.IOException;
+
+public class TestComments {
+ private FluentBundle bundle;
+
+ @Before
+ public void setUp() throws IOException {
+ this.bundle = GetFileHelper.getFluentBundle("comments.ftl");
+ }
+
+ @Test
+ public void testIfExceptions() {
+ Assertions.assertFalse(bundle.hasExceptions());
+ }
+
+ @Test
+ public void testMessage() {
+ Assertions.assertEquals("Foo", GetFileHelper.getMessage(bundle, "foo"));
+ }
+}
diff --git a/src/test/java/net/quickwrite/fluent4j/TestEOFComment.java b/src/test/java/net/quickwrite/fluent4j/TestEOFComment.java
new file mode 100644
index 00000000..09decf1c
--- /dev/null
+++ b/src/test/java/net/quickwrite/fluent4j/TestEOFComment.java
@@ -0,0 +1,22 @@
+package net.quickwrite.fluent4j;
+
+import net.quickwrite.fluent4j.util.bundle.FluentBundle;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.jupiter.api.Assertions;
+
+import java.io.IOException;
+
+public class TestEOFComment {
+ private FluentBundle bundle;
+
+ @Before
+ public void setUp() throws IOException {
+ this.bundle = GetFileHelper.getFluentBundle("eof_comment.ftl");
+ }
+
+ @Test
+ public void testIfExceptions() {
+ Assertions.assertFalse(bundle.hasExceptions());
+ }
+}
diff --git a/src/test/java/net/quickwrite/fluent4j/TestEOFEmpty.java b/src/test/java/net/quickwrite/fluent4j/TestEOFEmpty.java
new file mode 100644
index 00000000..39e0a7f3
--- /dev/null
+++ b/src/test/java/net/quickwrite/fluent4j/TestEOFEmpty.java
@@ -0,0 +1,22 @@
+package net.quickwrite.fluent4j;
+
+import net.quickwrite.fluent4j.util.bundle.FluentBundle;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.jupiter.api.Assertions;
+
+import java.io.IOException;
+
+public class TestEOFEmpty {
+ private FluentBundle bundle;
+
+ @Before
+ public void setUp() throws IOException {
+ this.bundle = GetFileHelper.getFluentBundle("eof_empty.ftl");
+ }
+
+ @Test
+ public void testIfExceptions() {
+ Assertions.assertFalse(bundle.hasExceptions());
+ }
+}
diff --git a/src/test/java/net/quickwrite/fluent4j/TestEOFId.java b/src/test/java/net/quickwrite/fluent4j/TestEOFId.java
new file mode 100644
index 00000000..17dd9787
--- /dev/null
+++ b/src/test/java/net/quickwrite/fluent4j/TestEOFId.java
@@ -0,0 +1,22 @@
+package net.quickwrite.fluent4j;
+
+import net.quickwrite.fluent4j.util.bundle.FluentBundle;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.jupiter.api.Assertions;
+
+import java.io.IOException;
+
+public class TestEOFId {
+ private FluentBundle bundle;
+
+ @Before
+ public void setUp() throws IOException {
+ this.bundle = GetFileHelper.getFluentBundle("eof_id.ftl");
+ }
+
+ @Test
+ public void testIfExceptions() {
+ Assertions.assertTrue(bundle.hasExceptions());
+ }
+}
diff --git a/src/test/java/net/quickwrite/fluent4j/TestEOFIdEquals.java b/src/test/java/net/quickwrite/fluent4j/TestEOFIdEquals.java
new file mode 100644
index 00000000..efea3fdd
--- /dev/null
+++ b/src/test/java/net/quickwrite/fluent4j/TestEOFIdEquals.java
@@ -0,0 +1,27 @@
+package net.quickwrite.fluent4j;
+
+import net.quickwrite.fluent4j.util.bundle.FluentBundle;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.jupiter.api.Assertions;
+
+import java.io.IOException;
+
+public class TestEOFIdEquals {
+ private FluentBundle bundle;
+
+ @Before
+ public void setUp() throws IOException {
+ this.bundle = GetFileHelper.getFluentBundle("eof_id_equals.ftl");
+ }
+
+ @Test
+ public void testIfExceptions() {
+ Assertions.assertFalse(bundle.hasExceptions());
+ }
+
+ @Test
+ public void testMessageId() {
+ Assertions.assertEquals("", GetFileHelper.getMessage(bundle, "message-id"));
+ }
+}
diff --git a/src/test/java/net/quickwrite/fluent4j/TestEOFJunk.java b/src/test/java/net/quickwrite/fluent4j/TestEOFJunk.java
new file mode 100644
index 00000000..3ed1bd74
--- /dev/null
+++ b/src/test/java/net/quickwrite/fluent4j/TestEOFJunk.java
@@ -0,0 +1,22 @@
+package net.quickwrite.fluent4j;
+
+import net.quickwrite.fluent4j.util.bundle.FluentBundle;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.jupiter.api.Assertions;
+
+import java.io.IOException;
+
+public class TestEOFJunk {
+ private FluentBundle bundle;
+
+ @Before
+ public void setUp() throws IOException {
+ this.bundle = GetFileHelper.getFluentBundle("eof_junk.ftl");
+ }
+
+ @Test
+ public void testIfExceptions() {
+ Assertions.assertTrue(bundle.hasExceptions());
+ }
+}
diff --git a/src/test/java/net/quickwrite/fluent4j/TestEOFValue.java b/src/test/java/net/quickwrite/fluent4j/TestEOFValue.java
new file mode 100644
index 00000000..ed6d0e31
--- /dev/null
+++ b/src/test/java/net/quickwrite/fluent4j/TestEOFValue.java
@@ -0,0 +1,27 @@
+package net.quickwrite.fluent4j;
+
+import net.quickwrite.fluent4j.util.bundle.FluentBundle;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.jupiter.api.Assertions;
+
+import java.io.IOException;
+
+public class TestEOFValue {
+ private FluentBundle bundle;
+
+ @Before
+ public void setUp() throws IOException {
+ this.bundle = GetFileHelper.getFluentBundle("eof_value.ftl");
+ }
+
+ @Test
+ public void testIfExceptions() {
+ Assertions.assertFalse(bundle.hasExceptions());
+ }
+
+ @Test
+ public void testMessageId() {
+ Assertions.assertEquals("No EOL", GetFileHelper.getMessage(bundle, "no-eol"));
+ }
+}
diff --git a/src/test/java/net/quickwrite/fluent4j/TestEscapedCharacters.java b/src/test/java/net/quickwrite/fluent4j/TestEscapedCharacters.java
new file mode 100644
index 00000000..2b6284e4
--- /dev/null
+++ b/src/test/java/net/quickwrite/fluent4j/TestEscapedCharacters.java
@@ -0,0 +1,92 @@
+package net.quickwrite.fluent4j;
+
+import net.quickwrite.fluent4j.util.bundle.FluentBundle;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.jupiter.api.Assertions;
+
+import java.io.IOException;
+
+public class TestEscapedCharacters {
+ private FluentBundle bundle;
+
+ @Before
+ public void setUp() throws IOException {
+ this.bundle = GetFileHelper.getFluentBundle("escaped_characters.ftl");
+ }
+
+ @Test
+ public void testTextBackslashOne() {
+ Assertions.assertEquals("Value with \\ a backslash", GetFileHelper.getMessage(bundle, "text-backslash-one"));
+ }
+
+ @Test
+ public void testTextBackslashTwo() {
+ Assertions.assertEquals("Value with \\\\ two backslashes", GetFileHelper.getMessage(bundle, "text-backslash-two"));
+ }
+
+ @Test
+ public void testTextBackslashBrace() {
+ Assertions.assertEquals("Value with \\{placeable}", GetFileHelper.getMessage(bundle, "text-backslash-brace"));
+ }
+
+ @Test
+ public void testTextBackslashU() {
+ Assertions.assertEquals("\\u0041", GetFileHelper.getMessage(bundle, "text-backslash-u"));
+ }
+
+ @Test
+ public void testTextBackslashBackslashU() {
+ Assertions.assertEquals("\\\\u0041", GetFileHelper.getMessage(bundle, "text-backslash-backslash-u"));
+ }
+
+ @Test
+ public void testQuoteInString() {
+ Assertions.assertEquals("\"", GetFileHelper.getMessage(bundle, "quote-in-string"));
+ }
+
+ @Test
+ public void testBackslashInString() {
+ Assertions.assertEquals("\\", GetFileHelper.getMessage(bundle, "backslash-in-string"));
+ }
+
+ @Test
+ public void testStringUnicode4Digits() {
+ Assertions.assertEquals("\u0041", GetFileHelper.getMessage(bundle, "string-unicode-4digits"));
+ }
+
+ @Test
+ public void testEscapeUnicode4Digits() {
+ Assertions.assertEquals("\\u0041", GetFileHelper.getMessage(bundle, "escape-unicode-4digits"));
+ }
+
+ @Test
+ public void testStringUnicode6Digits() {
+ Assertions.assertEquals("\uD83D\uDE02", GetFileHelper.getMessage(bundle, "string-unicode-6digits"));
+ }
+
+ @Test
+ public void testEscapeUnicode6Digits() {
+ Assertions.assertEquals("\\U01F602", GetFileHelper.getMessage(bundle, "escape-unicode-6digits"));
+ }
+
+ @Test
+ public void testStringTooMany4Digits() {
+ Assertions.assertEquals("\u004100", GetFileHelper.getMessage(bundle, "string-too-many-4digits"));
+ }
+
+ @Test
+ public void testStringTooMany6Digits() {
+ Assertions.assertEquals("\uD83D\uDE0200", GetFileHelper.getMessage(bundle, "string-too-many-6digits"));
+ }
+
+ @Test
+ public void testLiteralBraceOpen() {
+ Assertions.assertEquals("An opening { brace.", GetFileHelper.getMessage(bundle, "brace-open"));
+ }
+
+ @Test
+ public void testLiteralBraceClose() {
+ Assertions.assertEquals("A closing } brace.", GetFileHelper.getMessage(bundle, "brace-close"));
+ }
+}
diff --git a/src/test/java/net/quickwrite/fluent4j/TestJunk.java b/src/test/java/net/quickwrite/fluent4j/TestJunk.java
new file mode 100644
index 00000000..3754dcf7
--- /dev/null
+++ b/src/test/java/net/quickwrite/fluent4j/TestJunk.java
@@ -0,0 +1,22 @@
+package net.quickwrite.fluent4j;
+
+import net.quickwrite.fluent4j.util.bundle.FluentBundle;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.jupiter.api.Assertions;
+
+import java.io.IOException;
+
+public class TestJunk {
+ private FluentBundle bundle;
+
+ @Before
+ public void setUp() throws IOException {
+ this.bundle = GetFileHelper.getFluentBundle("junk.ftl");
+ }
+
+ @Test
+ public void testIfExceptions() {
+ Assertions.assertTrue(bundle.hasExceptions());
+ }
+}
diff --git a/src/test/java/net/quickwrite/fluent4j/TestLeadingDots.java b/src/test/java/net/quickwrite/fluent4j/TestLeadingDots.java
new file mode 100644
index 00000000..d3a581e2
--- /dev/null
+++ b/src/test/java/net/quickwrite/fluent4j/TestLeadingDots.java
@@ -0,0 +1,87 @@
+package net.quickwrite.fluent4j;
+
+import net.quickwrite.fluent4j.util.bundle.FluentBundle;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.jupiter.api.Assertions;
+
+import java.io.IOException;
+
+public class TestLeadingDots {
+ private FluentBundle bundle;
+
+ @Before
+ public void setUp() throws IOException {
+ this.bundle = GetFileHelper.getFluentBundle("leading_dots.ftl");
+ }
+
+ @Test
+ public void testKey01() {
+ Assertions.assertEquals(".Value", GetFileHelper.getMessage(bundle, "key01"));
+ }
+
+ @Test
+ public void testKey02() {
+ Assertions.assertEquals("…Value", GetFileHelper.getMessage(bundle, "key02"));
+ }
+
+ @Test
+ public void testKey03() {
+ Assertions.assertEquals(".Value", GetFileHelper.getMessage(bundle, "key03"));
+ }
+
+ @Test
+ public void testKey04() {
+ Assertions.assertEquals(".Value", GetFileHelper.getMessage(bundle, "key04"));
+ }
+
+ @Test
+ public void testKey05() {
+ Assertions.assertEquals("Value\n.Continued", GetFileHelper.getMessage(bundle, "key05"));
+ }
+
+ @Test
+ public void testKey06() {
+ Assertions.assertEquals(".Value\n.Continued", GetFileHelper.getMessage(bundle, "key06"));
+ }
+
+ @Test
+ public void testKey10() {
+ Assertions.assertEquals("", GetFileHelper.getMessage(bundle, "key10"));
+ }
+
+ @Test
+ public void testKey11() {
+ Assertions.assertEquals(".Value = which looks like an attribute\nContinued", GetFileHelper.getMessage(bundle, "key11"));
+ }
+
+ @Test
+ public void testKey12() {
+ Assertions.assertEquals("", GetFileHelper.getMessage(bundle, "key12"));
+ }
+
+ @Test
+ public void testKey13() {
+ Assertions.assertEquals("", GetFileHelper.getMessage(bundle, "key13"));
+ }
+
+ @Test
+ public void testKey14() {
+ Assertions.assertEquals("", GetFileHelper.getMessage(bundle, "key12"));
+ }
+
+ @Test
+ public void testKey15() {
+ Assertions.assertEquals(".Value", GetFileHelper.getMessage(bundle, "key15"));
+ }
+
+ @Test
+ public void testKey16() {
+ Assertions.assertEquals(".Value", GetFileHelper.getMessage(bundle, "key16"));
+ }
+
+ @Test
+ public void testKey17() {
+ Assertions.assertEquals("Value\n.Continued", GetFileHelper.getMessage(bundle, "key17"));
+ }
+}
diff --git a/src/test/java/net/quickwrite/fluent4j/TestLiteralExpressions.java b/src/test/java/net/quickwrite/fluent4j/TestLiteralExpressions.java
new file mode 100644
index 00000000..6c22d52c
--- /dev/null
+++ b/src/test/java/net/quickwrite/fluent4j/TestLiteralExpressions.java
@@ -0,0 +1,47 @@
+package net.quickwrite.fluent4j;
+
+import net.quickwrite.fluent4j.util.bundle.FluentBundle;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.jupiter.api.Assertions;
+
+import java.io.IOException;
+
+public class TestLiteralExpressions {
+ private FluentBundle bundle;
+
+ @Before
+ public void setUp() throws IOException {
+ this.bundle = GetFileHelper.getFluentBundle("literal_expressions.ftl");
+ }
+
+ @Test
+ public void testIfExceptions() {
+ Assertions.assertFalse(bundle.hasExceptions());
+ }
+
+ @Test
+ public void testStringExpression() {
+ Assertions.assertEquals("abc", GetFileHelper.getMessage(bundle, "string-expression"));
+ }
+
+ @Test
+ public void testNumberExpression() {
+ Assertions.assertEquals("123", GetFileHelper.getMessage(bundle, "number-expression"));
+ }
+
+ @Test
+ public void testNegativeNumberExpression() {
+ Assertions.assertEquals("-42", GetFileHelper.getMessage(bundle, "negative-number-expression"));
+ }
+
+ @Test
+ public void testFloatExpression() {
+ Assertions.assertEquals("3.141", GetFileHelper.getMessage(bundle, "float-expression"));
+ }
+
+ @Test
+ public void testNegativeFloatExpression() {
+ Assertions.assertEquals("-6.282", GetFileHelper.getMessage(bundle, "negative-float-expression"));
+ }
+}
diff --git a/src/test/java/net/quickwrite/fluent4j/TestMemberExpressions.java b/src/test/java/net/quickwrite/fluent4j/TestMemberExpressions.java
new file mode 100644
index 00000000..6700a010
--- /dev/null
+++ b/src/test/java/net/quickwrite/fluent4j/TestMemberExpressions.java
@@ -0,0 +1,42 @@
+package net.quickwrite.fluent4j;
+
+import net.quickwrite.fluent4j.util.bundle.FluentBundle;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.jupiter.api.Assertions;
+
+import java.io.IOException;
+
+public class TestMemberExpressions {
+ private FluentBundle bundle;
+
+ @Before
+ public void setUp() throws IOException {
+ this.bundle = GetFileHelper.getFluentBundle("member_expressions.ftl");
+ }
+
+ @Test
+ public void testIfExceptions() {
+ Assertions.assertFalse(bundle.hasExceptions());
+ }
+
+ @Test
+ public void testMessageAttributeExpressionPlaceable() {
+ Assertions.assertEquals("{msg.attr}", GetFileHelper.getMessage(bundle, "message-attribute-expression-placeable"));
+ }
+
+ @Test
+ public void testTermAttributeExpressionPlaceable() {
+ Assertions.assertEquals("{-term.attr}", GetFileHelper.getMessage(bundle, "term-attribute-expression-placeable"));
+ }
+
+ @Test
+ public void testTermAttributeExpressionSelector() {
+ Assertions.assertEquals("Value", GetFileHelper.getMessage(bundle, "term-attribute-expression-selector"));
+ }
+
+ @Test
+ public void testMessageAttributeExpressionSelector() {
+ Assertions.assertEquals("Value", GetFileHelper.getMessage(bundle, "message-attribute-expression-selector"));
+ }
+}
diff --git a/src/test/java/net/quickwrite/fluent4j/TestMessages.java b/src/test/java/net/quickwrite/fluent4j/TestMessages.java
new file mode 100644
index 00000000..37673af0
--- /dev/null
+++ b/src/test/java/net/quickwrite/fluent4j/TestMessages.java
@@ -0,0 +1,87 @@
+package net.quickwrite.fluent4j;
+
+import net.quickwrite.fluent4j.util.bundle.FluentBundle;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.jupiter.api.Assertions;
+
+import java.io.IOException;
+
+public class TestMessages {
+ private FluentBundle bundle;
+
+ @Before
+ public void setUp() throws IOException {
+ this.bundle = GetFileHelper.getFluentBundle("messages.ftl");
+ }
+
+ @Test
+ public void testIfExceptions() {
+ Assertions.assertTrue(bundle.hasExceptions());
+ }
+
+ @Test
+ public void testKey01() {
+ Assertions.assertEquals("Value", GetFileHelper.getMessage(bundle, "key01"));
+ }
+
+ @Test
+ public void testKey02() {
+ Assertions.assertEquals("Value2", GetFileHelper.getMessage(bundle, "key02"));
+ }
+
+ @Test
+ public void testKey03() {
+ Assertions.assertEquals("", GetFileHelper.getMessage(bundle, "key03"));
+ }
+
+ @Test
+ public void testKey04() {
+ Assertions.assertEquals("", GetFileHelper.getMessage(bundle, "key04"));
+ }
+
+ @Test
+ public void testKey05() {
+ Assertions.assertEquals("", GetFileHelper.getMessage(bundle, "key05"));
+ }
+
+ @Test
+ public void testNoWhitespace() {
+ Assertions.assertEquals("Value", GetFileHelper.getMessage(bundle, "no-whitespace"));
+ }
+
+ @Test
+ public void testExtraWhitespace() {
+ Assertions.assertEquals("Value", GetFileHelper.getMessage(bundle, "extra-whitespace"));
+ }
+
+ @Test
+ public void testKey06() {
+ Assertions.assertEquals("", GetFileHelper.getMessage(bundle, "key06"));
+ }
+
+ @Test
+ public void testKey09() {
+ Assertions.assertEquals("Value 09", GetFileHelper.getMessage(bundle, "KEY09"));
+ }
+
+ @Test
+ public void testKey10() {
+ Assertions.assertEquals("Value 10", GetFileHelper.getMessage(bundle, "key-10"));
+ }
+
+ @Test
+ public void testKey11() {
+ Assertions.assertEquals("Value 11", GetFileHelper.getMessage(bundle, "key_11"));
+ }
+
+ @Test
+ public void testKey12() {
+ Assertions.assertEquals("Value 12", GetFileHelper.getMessage(bundle, "key-12-"));
+ }
+
+ @Test
+ public void testKey13() {
+ Assertions.assertEquals("Value 13", GetFileHelper.getMessage(bundle, "key_13_"));
+ }
+}
diff --git a/src/test/java/net/quickwrite/fluent4j/TestMixedEntries.java b/src/test/java/net/quickwrite/fluent4j/TestMixedEntries.java
new file mode 100644
index 00000000..2a6e1b39
--- /dev/null
+++ b/src/test/java/net/quickwrite/fluent4j/TestMixedEntries.java
@@ -0,0 +1,52 @@
+package net.quickwrite.fluent4j;
+
+import net.quickwrite.fluent4j.util.bundle.FluentBundle;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.jupiter.api.Assertions;
+
+import java.io.IOException;
+
+public class TestMixedEntries {
+ private FluentBundle bundle;
+
+ @Before
+ public void setUp() throws IOException {
+ this.bundle = GetFileHelper.getFluentBundle("mixed_entries.ftl");
+ }
+
+ @Test
+ public void testIfExceptions() {
+ Assertions.assertTrue(bundle.hasExceptions());
+ }
+
+ @Test
+ public void testKey01() {
+ Assertions.assertEquals("", GetFileHelper.getMessage(bundle, "key01"));
+ }
+
+ @Test
+ public void testNonASCIICharacter1() {
+ Assertions.assertEquals("Custom Identifier", GetFileHelper.getMessage(bundle, "ą"));
+ }
+
+ @Test
+ public void testNonASCIICharacter2() {
+ Assertions.assertEquals("Another one", GetFileHelper.getMessage(bundle, "ć"));
+ }
+
+ @Test
+ public void testKey02() {
+ Assertions.assertEquals("Value", GetFileHelper.getMessage(bundle, "key02"));
+ }
+
+ @Test
+ public void testKey03() {
+ Assertions.assertEquals("Value 03", GetFileHelper.getMessage(bundle, "key03"));
+ }
+
+ @Test
+ public void testKey04() {
+ Assertions.assertEquals("Value 04", GetFileHelper.getMessage(bundle, "key04"));
+ }
+}
diff --git a/src/test/java/net/quickwrite/fluent4j/TestMultilineValues.java b/src/test/java/net/quickwrite/fluent4j/TestMultilineValues.java
new file mode 100644
index 00000000..c1786cea
--- /dev/null
+++ b/src/test/java/net/quickwrite/fluent4j/TestMultilineValues.java
@@ -0,0 +1,106 @@
+package net.quickwrite.fluent4j;
+
+import net.quickwrite.fluent4j.util.bundle.FluentBundle;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.jupiter.api.Assertions;
+
+import java.io.IOException;
+
+public class TestMultilineValues {
+ private FluentBundle bundle;
+
+ @Before
+ public void setUp() throws IOException {
+ this.bundle = GetFileHelper.getFluentBundle("multiline_values.ftl");
+ }
+
+ @Test
+ public void testIfExceptions() {
+ Assertions.assertFalse(bundle.hasExceptions());
+ }
+
+ @Test
+ public void testKey01() {
+ Assertions.assertEquals("""
+ A multiline value
+ continued on the next line
+
+ and also down here.""",
+ GetFileHelper.getMessage(bundle, "key01"));
+ }
+
+ @Test
+ public void testKey02() {
+ Assertions.assertEquals("""
+ A multiline value starting
+ on a new line.""",
+ GetFileHelper.getMessage(bundle, "key02"));
+ }
+
+ @Test
+ public void testKey03() {
+ Assertions.assertEquals("", GetFileHelper.getMessage(bundle, "key03"));
+ }
+
+ @Test
+ public void testKey04() {
+ Assertions.assertEquals("", GetFileHelper.getMessage(bundle, "key04"));
+ }
+
+ @Test
+ public void testKey05() {
+ Assertions.assertEquals("""
+ A multiline value with non-standard
+
+ indentation.""",
+ GetFileHelper.getMessage(bundle, "key05"));
+ }
+
+ @Test
+ public void testKey06() {
+ Assertions.assertEquals("""
+ A multiline value with placeables
+ at the beginning and the end
+ of lines.""",
+ GetFileHelper.getMessage(bundle, "key06"));
+ }
+
+ @Test
+ public void testKey07() {
+ Assertions.assertEquals("A multiline value starting and ending with a placeable", GetFileHelper.getMessage(bundle, "key07"));
+ }
+
+ @Test
+ public void testKey08() {
+ Assertions.assertEquals("Leading and trailing whitespace.", GetFileHelper.getMessage(bundle, "key08"));
+ }
+
+ @Test
+ public void testKey09() {
+ Assertions.assertEquals("""
+ zero
+ three
+ two
+ one
+ zero""",
+ GetFileHelper.getMessage(bundle, "key09"));
+ }
+
+ @Test
+ public void testKey10() {
+ Assertions.assertEquals("""
+ two
+ zero
+ four""",
+ GetFileHelper.getMessage(bundle, "key10"));
+ }
+
+ @Test
+ public void testKey11() {
+ Assertions.assertEquals("""
+ two
+ zero""",
+ GetFileHelper.getMessage(bundle, "key11"));
+ }
+}
diff --git a/src/test/java/net/quickwrite/fluent4j/TestNumbers.java b/src/test/java/net/quickwrite/fluent4j/TestNumbers.java
new file mode 100644
index 00000000..5bc1759e
--- /dev/null
+++ b/src/test/java/net/quickwrite/fluent4j/TestNumbers.java
@@ -0,0 +1,127 @@
+package net.quickwrite.fluent4j;
+
+import net.quickwrite.fluent4j.util.bundle.FluentBundle;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.jupiter.api.Assertions;
+
+import java.io.IOException;
+
+public class TestNumbers {
+ private FluentBundle bundle;
+
+ @Before
+ public void setUp() throws IOException {
+ this.bundle = GetFileHelper.getFluentBundle("numbers.ftl");
+ }
+
+ @Test
+ public void testIfExceptions() {
+ Assertions.assertTrue(bundle.hasExceptions());
+ }
+
+ @Test
+ public void testIntZero() {
+ Assertions.assertEquals("0", GetFileHelper.getMessage(bundle, "int-zero"));
+ }
+
+ @Test
+ public void testIntPositive() {
+ Assertions.assertEquals("1", GetFileHelper.getMessage(bundle, "int-positive"));
+ }
+
+ @Test
+ public void testIntNegative() {
+ Assertions.assertEquals("-1", GetFileHelper.getMessage(bundle, "int-negative"));
+ }
+
+ @Test
+ public void testIntNegativeZero() {
+ Assertions.assertEquals("0", GetFileHelper.getMessage(bundle, "int-negative-zero"));
+ }
+
+ @Test
+ public void testIntPositivePadded() {
+ Assertions.assertEquals("1", GetFileHelper.getMessage(bundle, "int-positive-padded"));
+ }
+
+ @Test
+ public void testIntNegativePadded() {
+ Assertions.assertEquals("-1", GetFileHelper.getMessage(bundle, "int-negative-padded"));
+ }
+
+ @Test
+ public void testIntZeroPadded() {
+ Assertions.assertEquals("0", GetFileHelper.getMessage(bundle, "int-zero-padded"));
+ }
+
+ @Test
+ public void testIntNegativeZeroPadded() {
+ Assertions.assertEquals("0", GetFileHelper.getMessage(bundle, "int-negative-zero-padded"));
+ }
+
+ @Test
+ public void testFloatZero() {
+ Assertions.assertEquals("0", GetFileHelper.getMessage(bundle, "float-zero"));
+ }
+
+ @Test
+ public void testFloatPositive() {
+ Assertions.assertEquals("0.01", GetFileHelper.getMessage(bundle, "float-positive"));
+ }
+
+ @Test
+ public void testFloatPositiveOne() {
+ Assertions.assertEquals("1.03", GetFileHelper.getMessage(bundle, "float-positive-one"));
+ }
+
+ @Test
+ public void testFloatPositiveWithoutFraction() {
+ Assertions.assertEquals("1", GetFileHelper.getMessage(bundle, "float-positive-without-fraction"));
+ }
+
+ @Test
+ public void testFloatNegative() {
+ Assertions.assertEquals("-0.01", GetFileHelper.getMessage(bundle, "float-negative"));
+ }
+
+ @Test
+ public void testFloatNegativeOne() {
+ Assertions.assertEquals("-1.03", GetFileHelper.getMessage(bundle, "float-negative-one"));
+ }
+
+ @Test
+ public void testFloatNegativeWithoutFraction() {
+ Assertions.assertEquals("-1", GetFileHelper.getMessage(bundle, "float-negative-without-fraction"));
+ }
+
+ @Test
+ public void testFloatPositivePaddedLeft() {
+ Assertions.assertEquals("1.03", GetFileHelper.getMessage(bundle, "float-positive-padded-left"));
+ }
+
+ @Test
+ public void testFloatPositivePaddedRight() {
+ Assertions.assertEquals("1.03", GetFileHelper.getMessage(bundle, "float-positive-padded-right"));
+ }
+
+ @Test
+ public void testFloatPositivePaddedBoth() {
+ Assertions.assertEquals("1.03", GetFileHelper.getMessage(bundle, "float-positive-padded-both"));
+ }
+
+ @Test
+ public void testFloatNegativePaddedLeft() {
+ Assertions.assertEquals("-1.03", GetFileHelper.getMessage(bundle, "float-negative-padded-left"));
+ }
+
+ @Test
+ public void testFloatNegativePaddedRight() {
+ Assertions.assertEquals("-1.03", GetFileHelper.getMessage(bundle, "float-negative-padded-right"));
+ }
+
+ @Test
+ public void testFloatNegativePaddedBoth() {
+ Assertions.assertEquals("-1.03", GetFileHelper.getMessage(bundle, "float-negative-padded-both"));
+ }
+}
diff --git a/src/test/java/net/quickwrite/fluent4j/TestReferenceExpressions.java b/src/test/java/net/quickwrite/fluent4j/TestReferenceExpressions.java
new file mode 100644
index 00000000..c37fa4e2
--- /dev/null
+++ b/src/test/java/net/quickwrite/fluent4j/TestReferenceExpressions.java
@@ -0,0 +1,62 @@
+package net.quickwrite.fluent4j;
+
+import net.quickwrite.fluent4j.builder.FluentArgsBuilder;
+import net.quickwrite.fluent4j.util.bundle.FluentBundle;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.jupiter.api.Assertions;
+
+import java.io.IOException;
+
+public class TestReferenceExpressions {
+ private FluentBundle bundle;
+
+ @Before
+ public void setUp() throws IOException {
+ this.bundle = GetFileHelper.getFluentBundle("reference_expressions.ftl");
+ }
+
+ @Test
+ public void testIfExceptions() {
+ Assertions.assertTrue(bundle.hasExceptions());
+ }
+
+ @Test
+ public void testMessageReferencePlaceable() {
+ Assertions.assertEquals("{msg}", GetFileHelper.getMessage(bundle, "message-reference-placeable"));
+ }
+
+ @Test
+ public void testTermReferencePlaceable() {
+ Assertions.assertEquals("{-term}", GetFileHelper.getMessage(bundle, "term-reference-placeable"));
+ }
+
+ @Test
+ public void testVariableReferencePlaceable() {
+ Assertions.assertEquals("{$var}", GetFileHelper.getMessage(bundle, "variable-reference-placeable"));
+ }
+
+ @Test
+ public void testVariableReferenceSelector() {
+ Assertions.assertEquals("Value", GetFileHelper.getMessage(bundle, "variable-reference-selector"));
+ }
+
+ @Test
+ public void testValidMessageReferencePlaceable() {
+ Assertions.assertEquals("Valid Message", GetFileHelper.getMessage(bundle, "valid-message-reference-placeable"));
+ }
+
+ @Test
+ public void testValidTermReferencePlaceable() {
+ Assertions.assertEquals("Valid Term", GetFileHelper.getMessage(bundle, "valid-term-reference-placeable"));
+ }
+
+ @Test
+ public void testValidVariableReferencePlaceable() {
+ Assertions.assertEquals("Value",
+ bundle.getMessage("valid-variable-reference-placeable",
+ new FluentArgsBuilder().set("var", "Value").build()
+ ).orElseThrow()
+ );
+ }
+}
diff --git a/src/test/java/net/quickwrite/fluent4j/TestSelectExpressions.java b/src/test/java/net/quickwrite/fluent4j/TestSelectExpressions.java
new file mode 100644
index 00000000..55eb18b7
--- /dev/null
+++ b/src/test/java/net/quickwrite/fluent4j/TestSelectExpressions.java
@@ -0,0 +1,47 @@
+package net.quickwrite.fluent4j;
+
+import net.quickwrite.fluent4j.util.bundle.FluentBundle;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.jupiter.api.Assertions;
+
+import java.io.IOException;
+
+public class TestSelectExpressions {
+ private FluentBundle bundle;
+
+ @Before
+ public void setUp() throws IOException {
+ this.bundle = GetFileHelper.getFluentBundle("select_expressions.ftl");
+ }
+
+ @Test
+ public void testIfExceptions() {
+ Assertions.assertTrue(bundle.hasExceptions());
+ }
+
+ @Test
+ public void testNewMessages() {
+ Assertions.assertEquals("Other", GetFileHelper.getMessage(bundle, "new-messages"));
+ }
+
+ @Test
+ public void testValidSelectorTermAttribute() {
+ Assertions.assertEquals("Value", GetFileHelper.getMessage(bundle, "valid-selector-term-attribute"));
+ }
+
+ @Test
+ public void testEmptyVariant() {
+ Assertions.assertEquals("", GetFileHelper.getMessage(bundle, "empty-variant"));
+ }
+
+ @Test
+ public void testReducedWhitespace() {
+ Assertions.assertEquals("", GetFileHelper.getMessage(bundle, "reduced-whitespace"));
+ }
+
+ @Test
+ public void testNestedSelect() {
+ Assertions.assertEquals("Value", GetFileHelper.getMessage(bundle, "nested-select"));
+ }
+}
diff --git a/src/test/java/net/quickwrite/fluent4j/TestSparseEntries.java b/src/test/java/net/quickwrite/fluent4j/TestSparseEntries.java
new file mode 100644
index 00000000..417279c3
--- /dev/null
+++ b/src/test/java/net/quickwrite/fluent4j/TestSparseEntries.java
@@ -0,0 +1,55 @@
+package net.quickwrite.fluent4j;
+
+import net.quickwrite.fluent4j.util.bundle.FluentBundle;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.jupiter.api.Assertions;
+
+import java.io.IOException;
+
+public class TestSparseEntries {
+ private FluentBundle bundle;
+
+ @Before
+ public void setUp() throws IOException {
+ this.bundle = GetFileHelper.getFluentBundle("sparse_entries.ftl");
+ }
+
+ @Test
+ public void testIfExceptions() {
+ Assertions.assertFalse(bundle.hasExceptions());
+ }
+
+ @Test
+ public void testKey01() {
+ Assertions.assertEquals("Value", GetFileHelper.getMessage(bundle, "key01"));
+ }
+
+ @Test
+ public void testKey02() {
+ Assertions.assertEquals("", GetFileHelper.getMessage(bundle, "key02"));
+ }
+
+ @Test
+ public void testKey03() {
+ Assertions.assertEquals("""
+ Value
+ Continued
+
+
+ Over multiple
+ Lines""",
+ GetFileHelper.getMessage(bundle, "key03")
+ );
+ }
+
+ @Test
+ public void testKey05() {
+ Assertions.assertEquals("Value", GetFileHelper.getMessage(bundle, "key05"));
+ }
+
+ @Test
+ public void testKey06() {
+ Assertions.assertEquals("One", GetFileHelper.getMessage(bundle, "key06"));
+ }
+}
diff --git a/src/test/java/net/quickwrite/fluent4j/TestTab.java b/src/test/java/net/quickwrite/fluent4j/TestTab.java
new file mode 100644
index 00000000..1da580be
--- /dev/null
+++ b/src/test/java/net/quickwrite/fluent4j/TestTab.java
@@ -0,0 +1,37 @@
+package net.quickwrite.fluent4j;
+
+import net.quickwrite.fluent4j.util.bundle.FluentBundle;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.jupiter.api.Assertions;
+
+import java.io.IOException;
+
+public class TestTab {
+ private FluentBundle bundle;
+
+ @Before
+ public void setUp() throws IOException {
+ this.bundle = GetFileHelper.getFluentBundle("tab.ftl");
+ }
+
+ @Test
+ public void testIfExceptions() {
+ Assertions.assertTrue(bundle.hasExceptions());
+ }
+
+ @Test
+ public void testKey01() {
+ Assertions.assertEquals("\tValue 01", GetFileHelper.getMessage(bundle, "key01"));
+ }
+
+ @Test
+ public void testKey03() {
+ Assertions.assertEquals("", GetFileHelper.getMessage(bundle, "key03"));
+ }
+
+ @Test
+ public void testKey04() {
+ Assertions.assertEquals("This line is indented by 4 spaces,", GetFileHelper.getMessage(bundle, "key04"));
+ }
+}
diff --git a/src/test/java/net/quickwrite/fluent4j/TestTermParameters.java b/src/test/java/net/quickwrite/fluent4j/TestTermParameters.java
new file mode 100644
index 00000000..9ea7bd43
--- /dev/null
+++ b/src/test/java/net/quickwrite/fluent4j/TestTermParameters.java
@@ -0,0 +1,42 @@
+package net.quickwrite.fluent4j;
+
+import net.quickwrite.fluent4j.util.bundle.FluentBundle;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.jupiter.api.Assertions;
+
+import java.io.IOException;
+
+public class TestTermParameters {
+ private FluentBundle bundle;
+
+ @Before
+ public void setUp() throws IOException {
+ this.bundle = GetFileHelper.getFluentBundle("term_parameters.ftl");
+ }
+
+ @Test
+ public void testIfExceptions() {
+ Assertions.assertFalse(bundle.hasExceptions());
+ }
+
+ @Test
+ public void testKey01() {
+ Assertions.assertEquals("Value", GetFileHelper.getMessage(bundle, "key01"));
+ }
+
+ @Test
+ public void testKey02() {
+ Assertions.assertEquals("Value", GetFileHelper.getMessage(bundle, "key02"));
+ }
+
+ @Test
+ public void testKey03() {
+ Assertions.assertEquals("Value", GetFileHelper.getMessage(bundle, "key03"));
+ }
+
+ @Test
+ public void testKey04() {
+ Assertions.assertEquals("Value", GetFileHelper.getMessage(bundle, "key04"));
+ }
+}
diff --git a/src/test/java/net/quickwrite/fluent4j/TestVariables.java b/src/test/java/net/quickwrite/fluent4j/TestVariables.java
new file mode 100644
index 00000000..a8491160
--- /dev/null
+++ b/src/test/java/net/quickwrite/fluent4j/TestVariables.java
@@ -0,0 +1,58 @@
+package net.quickwrite.fluent4j;
+
+import net.quickwrite.fluent4j.builder.FluentArgsBuilder;
+import net.quickwrite.fluent4j.util.args.FluentArgs;
+import net.quickwrite.fluent4j.util.bundle.FluentBundle;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.jupiter.api.Assertions;
+
+import java.io.IOException;
+
+public class TestVariables {
+ private FluentBundle bundle;
+ private FluentArgs arguments;
+
+ @Before
+ public void setUp() throws IOException {
+ this.bundle = GetFileHelper.getFluentBundle("variables.ftl");
+ this.arguments = new FluentArgsBuilder().set("var", "Value").build();
+ }
+
+ @Test
+ public void testIfExceptions() {
+ Assertions.assertTrue(bundle.hasExceptions());
+ }
+
+ @Test
+ public void testKey01() {
+ Assertions.assertEquals(
+ "Value",
+ bundle.getMessage("key01", arguments).orElseThrow()
+ );
+ }
+
+ @Test
+ public void testKey02() {
+ Assertions.assertEquals(
+ "Value",
+ bundle.getMessage("key02", arguments).orElseThrow()
+ );
+ }
+
+ @Test
+ public void testKey03() {
+ Assertions.assertEquals(
+ "Value",
+ bundle.getMessage("key03", arguments).orElseThrow()
+ );
+ }
+
+ @Test
+ public void testKey04() {
+ Assertions.assertEquals(
+ "Value",
+ bundle.getMessage("key04", arguments).orElseThrow()
+ );
+ }
+}
diff --git a/src/test/java/net/quickwrite/fluent4j/TestVariantKeys.java b/src/test/java/net/quickwrite/fluent4j/TestVariantKeys.java
new file mode 100644
index 00000000..37c2ecaf
--- /dev/null
+++ b/src/test/java/net/quickwrite/fluent4j/TestVariantKeys.java
@@ -0,0 +1,42 @@
+package net.quickwrite.fluent4j;
+
+import net.quickwrite.fluent4j.util.bundle.FluentBundle;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.jupiter.api.Assertions;
+
+import java.io.IOException;
+
+public class TestVariantKeys {
+ private FluentBundle bundle;
+
+ @Before
+ public void setUp() throws IOException {
+ this.bundle = GetFileHelper.getFluentBundle("variant_keys.ftl");
+ }
+
+ @Test
+ public void testIfExceptions() {
+ Assertions.assertTrue(bundle.hasExceptions());
+ }
+
+ @Test
+ public void testSimpleIdentifier() {
+ Assertions.assertEquals("Value", GetFileHelper.getMessage(bundle, "simple-identifier"));
+ }
+
+ @Test
+ public void testIdentifierSurroundedByWhitespace() {
+ Assertions.assertEquals("Value", GetFileHelper.getMessage(bundle, "identifier-surrounded-by-whitespace"));
+ }
+
+ @Test
+ public void testIntNumberIdentifier() {
+ Assertions.assertEquals("Value", GetFileHelper.getMessage(bundle, "int-number"));
+ }
+
+ @Test
+ public void testFloatNumberIdentifier() {
+ Assertions.assertEquals("Value", GetFileHelper.getMessage(bundle, "float-number"));
+ }
+}
diff --git a/src/test/java/net/quickwrite/fluent4j/TestWhitespaceInValue.java b/src/test/java/net/quickwrite/fluent4j/TestWhitespaceInValue.java
new file mode 100644
index 00000000..068646da
--- /dev/null
+++ b/src/test/java/net/quickwrite/fluent4j/TestWhitespaceInValue.java
@@ -0,0 +1,37 @@
+package net.quickwrite.fluent4j;
+
+import net.quickwrite.fluent4j.util.bundle.FluentBundle;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.jupiter.api.Assertions;
+
+import java.io.IOException;
+
+public class TestWhitespaceInValue {
+ private FluentBundle bundle;
+
+ @Before
+ public void setUp() throws IOException {
+ this.bundle = GetFileHelper.getFluentBundle("whitespace_in_value.ftl");
+ }
+
+ @Test
+ public void testIfExceptions() {
+ Assertions.assertFalse(bundle.hasExceptions());
+ }
+
+ @Test
+ public void testKey() {
+ Assertions.assertEquals("""
+ first line
+
+
+
+
+
+
+ last line""",
+ GetFileHelper.getMessage(bundle, "key")
+ );
+ }
+}
diff --git a/src/test/java/net/quickwrite/fluent4j/TestZeroLength.java b/src/test/java/net/quickwrite/fluent4j/TestZeroLength.java
new file mode 100644
index 00000000..298582b5
--- /dev/null
+++ b/src/test/java/net/quickwrite/fluent4j/TestZeroLength.java
@@ -0,0 +1,22 @@
+package net.quickwrite.fluent4j;
+
+import net.quickwrite.fluent4j.util.bundle.FluentBundle;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.jupiter.api.Assertions;
+
+import java.io.IOException;
+
+public class TestZeroLength {
+ private FluentBundle bundle;
+
+ @Before
+ public void setUp() throws IOException {
+ this.bundle = GetFileHelper.getFluentBundle("zero_length.ftl");
+ }
+
+ @Test
+ public void testIfExceptions() {
+ Assertions.assertFalse(bundle.hasExceptions());
+ }
+}
diff --git a/src/test/resources/input/comments.ftl b/src/test/resources/input/comments.ftl
index d3566930..638ac16e 100644
--- a/src/test/resources/input/comments.ftl
+++ b/src/test/resources/input/comments.ftl
@@ -13,8 +13,3 @@ foo = Foo
# with indent
## Group Comment
### Resource Comment
-
-# Errors
-#error
-##error
-###error
diff --git a/src/test/resources/input/leading_dots.ftl b/src/test/resources/input/leading_dots.ftl
index 0b9d6693..cd6ccd1c 100644
--- a/src/test/resources/input/leading_dots.ftl
+++ b/src/test/resources/input/leading_dots.ftl
@@ -50,27 +50,14 @@ key15 =
{"."}Value
}
-# JUNK (variant must have a value)
key16 =
{ 1 ->
*[one]
.Value
}
-# JUNK (unclosed placeable)
key17 =
{ 1 ->
*[one] Value
.Continued
}
-
-# JUNK (attr .Value must have a value)
-key18 =
-.Value
-
-key19 =
-.attribute = Value
- Continued
-
-key20 =
-{"."}Value
diff --git a/src/test/resources/input/literal_expressions.ftl b/src/test/resources/input/literal_expressions.ftl
index 937b8a17..4124f5ca 100644
--- a/src/test/resources/input/literal_expressions.ftl
+++ b/src/test/resources/input/literal_expressions.ftl
@@ -1,3 +1,9 @@
string-expression = {"abc"}
+
number-expression = {123}
-number-expression = {-3.14}
+
+negative-number-expression = {-42}
+
+float-expression = {3.141}
+
+negative-float-expression = {-6.282}
diff --git a/src/test/resources/input/member_expressions.ftl b/src/test/resources/input/member_expressions.ftl
index 8bee3cd7..9cf09233 100644
--- a/src/test/resources/input/member_expressions.ftl
+++ b/src/test/resources/input/member_expressions.ftl
@@ -1,19 +1,16 @@
## Member expressions in placeables.
-# OK Message attributes may be interpolated in values.
message-attribute-expression-placeable = {msg.attr}
-# ERROR Term attributes may not be used for interpolation.
term-attribute-expression-placeable = {-term.attr}
## Member expressions in selectors.
-# OK Term attributes may be used as selectors.
term-attribute-expression-selector = {-term.attr ->
*[key] Value
}
-# ERROR Message attributes may not be used as selectors.
+
message-attribute-expression-selector = {msg.attr ->
*[key] Value
}
diff --git a/src/test/resources/input/messages.ftl b/src/test/resources/input/messages.ftl
index dbc616ee..cd5637cd 100644
--- a/src/test/resources/input/messages.ftl
+++ b/src/test/resources/input/messages.ftl
@@ -3,7 +3,7 @@ key01 = Value
key02 = Value
.attr = Attribute
-key02 = Value
+key02 = Value2
.attr1 = Attribute 1
.attr2 = Attribute 2
diff --git a/src/test/resources/input/mixed_entries.ftl b/src/test/resources/input/mixed_entries.ftl
index 99cc023d..444dc67e 100644
--- a/src/test/resources/input/mixed_entries.ftl
+++ b/src/test/resources/input/mixed_entries.ftl
@@ -9,7 +9,7 @@
key01 =
.attr = Attribute
-ą=Invalid identifier
+ą=Custom Identifier
ć=Another one
# Message Comment
diff --git a/src/test/resources/input/multiline_values.ftl b/src/test/resources/input/multiline_values.ftl
index e3739bb5..bf50075c 100644
--- a/src/test/resources/input/multiline_values.ftl
+++ b/src/test/resources/input/multiline_values.ftl
@@ -51,10 +51,3 @@ key11 =
two
zero
-key12 =
-{"."}
- four
-
-key13 =
- four
-{"."}
diff --git a/src/test/resources/input/obsolete.ftl b/src/test/resources/input/obsolete.ftl
deleted file mode 100644
index e0869e3a..00000000
--- a/src/test/resources/input/obsolete.ftl
+++ /dev/null
@@ -1,29 +0,0 @@
-### The syntax in this file has been discontinued. It is no longer part of the
-### Fluent specification and should not be implemented nor used. We're keeping
-### these fixtures around to protect against accidental syntax reuse.
-
-
-## Variant lists.
-
-message-variant-list =
- {
- *[key] Value
- }
-
--term-variant-list =
- {
- *[key] Value
- }
-
-
-## Variant expressions.
-
-message-variant-expression-placeable = {msg[case]}
-message-variant-expression-selector = {msg[case] ->
- *[key] Value
-}
-
-term-variant-expression-placeable = {-term[case]}
-term-variant-expression-selector = {-term[case] ->
- *[key] Value
-}
diff --git a/src/test/resources/input/placeables.ftl b/src/test/resources/input/placeables.ftl
deleted file mode 100644
index 7a1b280f..00000000
--- a/src/test/resources/input/placeables.ftl
+++ /dev/null
@@ -1,15 +0,0 @@
-nested-placeable = {{{1}}}
-padded-placeable = { 1 }
-sparse-placeable = { { 1 } }
-
-# ERROR Unmatched opening brace
-unmatched-open1 = { 1
-
-# ERROR Unmatched opening brace
-unmatched-open2 = {{ 1 }
-
-# ERROR Unmatched closing brace
-unmatched-close1 = 1 }
-
-# ERROR Unmatched closing brace
-unmatched-close2 = { 1 }}
diff --git a/src/test/resources/input/reference_expressions.ftl b/src/test/resources/input/reference_expressions.ftl
index 5b03334f..224db747 100644
--- a/src/test/resources/input/reference_expressions.ftl
+++ b/src/test/resources/input/reference_expressions.ftl
@@ -4,11 +4,6 @@ message-reference-placeable = {msg}
term-reference-placeable = {-term}
variable-reference-placeable = {$var}
-# Function references are invalid outside of call expressions.
-# This parses as a valid MessageReference.
-function-reference-placeable = {FUN}
-
-
## Reference expressions in selectors.
variable-reference-selector = {$var ->
@@ -23,8 +18,11 @@ message-reference-selector = {msg ->
term-reference-selector = {-term ->
*[key] Value
}
-# ERROR Function references are invalid outside of call expressions, and this
-# parses as a MessageReference which isn't a valid selector.
-function-expression-selector = {FUN ->
- *[key] Value
-}
+
+## Check if valid references work
+valid-message-reference-placeable = {valid-msg}
+valid-term-reference-placeable = {-valid-term}
+valid-variable-reference-placeable = {$var}
+
+valid-msg = Valid Message
+-valid-term = Valid Term
diff --git a/src/test/resources/input/select_expressions.ftl b/src/test/resources/input/select_expressions.ftl
index 603a1226..467b3227 100644
--- a/src/test/resources/input/select_expressions.ftl
+++ b/src/test/resources/input/select_expressions.ftl
@@ -6,33 +6,19 @@ new-messages =
valid-selector-term-attribute =
{ -term.case ->
- *[key] value
+ *[key] Value
}
# ERROR Term values are not valid selectors
invalid-selector-term-value =
{ -term ->
- *[key] value
+ *[key] Value
}
# ERROR CallExpressions on Terms are similar to TermReferences
invalid-selector-term-variant =
{ -term(case: "nominative") ->
- *[key] value
- }
-
-# ERROR Nested expressions are not valid selectors
-invalid-selector-nested-expression =
- { { 3 } ->
- *[key] default
- }
-
-# ERROR Select expressions are not valid selectors
-invalid-selector-select-expression =
- { { $sel ->
- *[key] value
- } ->
- *[key] default
+ *[key] Value
}
empty-variant =
diff --git a/src/test/resources/input/select_indent.ftl b/src/test/resources/input/select_indent.ftl
deleted file mode 100644
index 7455e935..00000000
--- a/src/test/resources/input/select_indent.ftl
+++ /dev/null
@@ -1,96 +0,0 @@
-select-1tbs-inline = { $selector ->
- *[key] Value
-}
-
-select-1tbs-newline = {
-$selector ->
- *[key] Value
-}
-
-select-1tbs-indent = {
- $selector ->
- *[key] Value
-}
-
-select-allman-inline =
-{ $selector ->
- *[key] Value
- [other] Other
-}
-
-select-allman-newline =
-{
-$selector ->
- *[key] Value
-}
-
-select-allman-indent =
-{
- $selector ->
- *[key] Value
-}
-
-select-gnu-inline =
- { $selector ->
- *[key] Value
- }
-
-select-gnu-newline =
- {
-$selector ->
- *[key] Value
- }
-
-select-gnu-indent =
- {
- $selector ->
- *[key] Value
- }
-
-select-no-indent =
-{
-$selector ->
-*[key] Value
-[other] Other
-}
-
-select-no-indent-multiline =
-{
-$selector ->
-*[key] Value
- Continued
-[other]
- Other
- Multiline
-}
-
-# ERROR (Multiline text must be indented)
-select-no-indent-multiline = { $selector ->
- *[key] Value
-Continued without indent.
-}
-
-select-flat =
-{
-$selector
-->
-*[
-key
-] Value
-[
-other
-] Other
-}
-
-# Each line ends with 5 spaces.
-select-flat-with-trailing-spaces =
-{
-$selector
-->
-*[
-key
-] Value
-[
-other
-] Other
-}
diff --git a/src/test/resources/input/special_chars.ftl b/src/test/resources/input/special_chars.ftl
deleted file mode 100644
index 5224bad7..00000000
--- a/src/test/resources/input/special_chars.ftl
+++ /dev/null
@@ -1,14 +0,0 @@
-## OK
-
-bracket-inline = [Value]
-dot-inline = .Value
-star-inline = *Value
-
-## ERRORS
-
-bracket-newline =
- [Value]
-dot-newline =
- .Value
-star-newline =
- *Value
diff --git a/src/test/resources/input/terms.ftl b/src/test/resources/input/terms.ftl
deleted file mode 100644
index 893188d4..00000000
--- a/src/test/resources/input/terms.ftl
+++ /dev/null
@@ -1,29 +0,0 @@
--term01 = Value
- .attr = Attribute
-
--term02 = {""}
-
-# JUNK Missing value
--term03 =
- .attr = Attribute
-
-# JUNK Missing value
-# < whitespace >
--term04 =
- .attr1 = Attribute 1
-
-# JUNK Missing value
--term05 =
-
-# JUNK Missing value
-# < whitespace >
--term06 =
-
-# JUNK Missing =
--term07
-
--term08=Value
- .attr=Attribute
-
--term09 = Value
- .attr = Attribute
diff --git a/src/test/resources/input/variant_keys.ftl b/src/test/resources/input/variant_keys.ftl
index 52f8ca61..346361b4 100644
--- a/src/test/resources/input/variant_keys.ftl
+++ b/src/test/resources/input/variant_keys.ftl
@@ -1,37 +1,37 @@
simple-identifier =
{ $sel ->
- *[key] value
+ *[key] Value
}
identifier-surrounded-by-whitespace =
{ $sel ->
- *[ key ] value
+ *[ key ] Value
}
int-number =
{ $sel ->
- *[1] value
+ *[1] Value
}
float-number =
{ $sel ->
- *[3.14] value
+ *[3.14] Value
}
# ERROR
invalid-identifier =
{ $sel ->
- *[two words] value
+ *[two words] Value
}
# ERROR
invalid-int =
{ $sel ->
- *[1 apple] value
+ *[1 apple] Value
}
# ERROR
invalid-int =
{ $sel ->
- *[3.14 apples] value
+ *[3.14 apples] Value
}