Skip to content

Commit 5186fc4

Browse files
Deprecates !constant, adds !const and !var (see #253).
1 parent d32faa9 commit 5186fc4

15 files changed

+229
-132
lines changed

changelog.md

+1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
- structurizr-core: `ViewSet.isEmpty()` was missing a check for image views.
66
- structurizr-dsl: Fixes https://github.com/structurizr/java/issues/252 (DSL parser does not seem to handle curly brackets balance).
7+
- structurizr-dsl: Deprecates `!constant`, adds `!const` and `!var` (see https://github.com/structurizr/java/issues/253).
78

89
## 2.0.0 (22nd February 2024)
910

structurizr-dsl/src/main/java/com/structurizr/dsl/Constant.java

-21
This file was deleted.

structurizr-dsl/src/main/java/com/structurizr/dsl/ConstantParser.java

-33
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
package com.structurizr.dsl;
2+
3+
class NameValuePair {
4+
5+
private NameValueType type;
6+
private final String name;
7+
private final String value;
8+
9+
NameValuePair(String name, String value) {
10+
this.name = name;
11+
this.value = value;
12+
}
13+
14+
NameValueType getType() {
15+
return type;
16+
}
17+
18+
void setType(NameValueType type) {
19+
this.type = type;
20+
}
21+
22+
String getName() {
23+
return name;
24+
}
25+
26+
String getValue() {
27+
return value;
28+
}
29+
30+
}
31+
32+
enum NameValueType {
33+
34+
Constant,
35+
Variable
36+
37+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
package com.structurizr.dsl;
2+
3+
final class NameValueParser extends AbstractParser {
4+
5+
private static final String GRAMMAR = "%s <name> <value>";
6+
7+
private static final int KEYWORD_INDEX = 0;
8+
private static final int NAME_INDEX = 1;
9+
private static final int VALUE_INDEX = 2;
10+
11+
private static final String NAME_REGEX = "[a-zA-Z0-9-_.]+";
12+
13+
NameValuePair parseConstant(Tokens tokens) {
14+
NameValuePair nvp = parse(tokens);
15+
nvp.setType(NameValueType.Constant);
16+
17+
return nvp;
18+
}
19+
20+
NameValuePair parseVariable(Tokens tokens) {
21+
NameValuePair nvp = parse(tokens);
22+
nvp.setType(NameValueType.Variable);
23+
24+
return nvp;
25+
}
26+
27+
private NameValuePair parse(Tokens tokens) {
28+
// !const name value
29+
// !var name value
30+
31+
if (tokens.hasMoreThan(VALUE_INDEX)) {
32+
throw new RuntimeException("Too many tokens, expected: " + String.format(GRAMMAR, tokens.get(KEYWORD_INDEX)));
33+
}
34+
35+
if (!tokens.includes(VALUE_INDEX)) {
36+
throw new RuntimeException("Expected: " + String.format(GRAMMAR, tokens.get(KEYWORD_INDEX)));
37+
}
38+
39+
String name = tokens.get(NAME_INDEX);
40+
String value = tokens.get(VALUE_INDEX);
41+
42+
if (!name.matches(NAME_REGEX)) {
43+
throw new RuntimeException("Constant/variable names must only contain the following characters: a-zA-Z0-9-_.");
44+
}
45+
46+
return new NameValuePair(name, value);
47+
}
48+
49+
}

structurizr-dsl/src/main/java/com/structurizr/dsl/StructurizrDslParser.java

+26-8
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ public final class StructurizrDslParser extends StructurizrDslTokens {
4242
private final Stack<DslContext> contextStack;
4343
private final Set<String> parsedTokens = new HashSet<>();
4444
private final IdentifiersRegister identifiersRegister;
45-
private final Map<String, Constant> constants;
45+
private final Map<String, NameValuePair> constantsAndVariables;
4646

4747
private final List<String> dslSourceLines = new ArrayList<>();
4848
private Workspace workspace;
@@ -56,7 +56,7 @@ public final class StructurizrDslParser extends StructurizrDslTokens {
5656
public StructurizrDslParser() {
5757
contextStack = new Stack<>();
5858
identifiersRegister = new IdentifiersRegister();
59-
constants = new HashMap<>();
59+
constantsAndVariables = new HashMap<>();
6060
}
6161

6262
/**
@@ -872,11 +872,29 @@ void parse(List<String> lines, File dslFile, boolean include) throws Structurizr
872872
}
873873

874874
} else if (CONSTANT_TOKEN.equalsIgnoreCase(firstToken)) {
875-
Constant constant = new ConstantParser().parse(getContext(), tokens);
876-
if (constants.containsKey(constant.getName())) {
877-
log.warn("A constant named " + constant.getName() + " already exists");
875+
log.warn("!constant has been deprecated and will be removed in a future release - please use !const or !var instead");
876+
NameValuePair nameValuePair = new NameValueParser().parseConstant(tokens);
877+
878+
if (constantsAndVariables.containsKey(nameValuePair.getName())) {
879+
log.warn("A constant \"" + nameValuePair.getName() + "\" already exists");
880+
}
881+
constantsAndVariables.put(nameValuePair.getName(), nameValuePair);
882+
883+
} else if (CONST_TOKEN.equalsIgnoreCase(firstToken)) {
884+
NameValuePair nameValuePair = new NameValueParser().parseConstant(tokens);
885+
886+
if (constantsAndVariables.containsKey(nameValuePair.getName())) {
887+
throw new StructurizrDslParserException("A constant/variable \"" + nameValuePair.getName() + "\" already exists");
888+
}
889+
constantsAndVariables.put(nameValuePair.getName(), nameValuePair);
890+
891+
} else if (VAR_TOKEN.equalsIgnoreCase(firstToken)) {
892+
NameValuePair nameValuePair = new NameValueParser().parseVariable(tokens);
893+
894+
if (constantsAndVariables.containsKey(nameValuePair.getName()) && constantsAndVariables.get(nameValuePair.getName()).getType() == NameValueType.Constant) {
895+
throw new StructurizrDslParserException("A constant \"" + nameValuePair.getName() + "\" already exists");
878896
}
879-
constants.put(constant.getName(), constant);
897+
constantsAndVariables.put(nameValuePair.getName(), nameValuePair);
880898

881899
} else if (IDENTIFIERS_TOKEN.equalsIgnoreCase(firstToken) && (inContext(WorkspaceDslContext.class) || inContext(ModelDslContext.class))) {
882900
setIdentifierScope(new IdentifierScopeParser().parse(getContext(), tokens));
@@ -963,8 +981,8 @@ private String substituteStrings(String token) {
963981
String before = m.group(0);
964982
String after = null;
965983
String name = before.substring(2, before.length()-1);
966-
if (constants.containsKey(name)) {
967-
after = constants.get(name).getValue();
984+
if (constantsAndVariables.containsKey(name)) {
985+
after = constantsAndVariables.get(name).getValue();
968986
} else {
969987
if (!restricted) {
970988
String environmentVariable = System.getenv().get(name);

structurizr-dsl/src/main/java/com/structurizr/dsl/StructurizrDslParserException.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ public final class StructurizrDslParserException extends Exception {
2323
}
2424

2525
StructurizrDslParserException(String message, File dslFile, int lineNumber, String line) {
26-
super((message.endsWith(".") ? message.substring(0, message.length()-1) : message) + " at line " + lineNumber + (dslFile != null ? " of " + dslFile.getAbsolutePath() : "") + ": " + line.trim());
26+
super((message.endsWith(".") ? message.substring(0, message.length()-1) : message) + " at line " + lineNumber + (dslFile != null && dslFile.isFile() ? " of " + dslFile.getAbsolutePath() : "") + ": " + line.trim());
2727
this.lineNumber = lineNumber;
2828
this.line = line;
2929
}

structurizr-dsl/src/main/java/com/structurizr/dsl/StructurizrDslTokens.java

+2
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,8 @@ class StructurizrDslTokens {
100100
static final String ADRS_TOKEN = "!adrs";
101101
static final String DECISIONS_TOKEN = "!decisions";
102102
static final String CONSTANT_TOKEN = "!constant";
103+
static final String CONST_TOKEN = "!const";
104+
static final String VAR_TOKEN = "!var";
103105
static final String IDENTIFIERS_TOKEN = "!identifiers";
104106
static final String IMPLIED_RELATIONSHIPS_TOKEN = "!impliedRelationships";
105107
static final String REF_TOKEN = "!ref";

structurizr-dsl/src/test/java/com/structurizr/dsl/ConstantParserTests.java

-59
This file was deleted.

structurizr-dsl/src/test/java/com/structurizr/dsl/DslTests.java

+35-3
Original file line numberDiff line numberDiff line change
@@ -364,17 +364,17 @@ void test_includeLocalDirectory() throws Exception {
364364
assertEquals("workspace {\n" +
365365
"\n" +
366366
" model {\n" +
367-
" !constant SOFTWARE_SYSTEM_NAME \"Software System 1\"\n" +
367+
" !var SOFTWARE_SYSTEM_NAME \"Software System 1\"\n" +
368368
" softwareSystem \"${SOFTWARE_SYSTEM_NAME}\" {\n" +
369369
" !docs ../../docs\n" +
370370
" }\n" +
371371
"\n" +
372-
" !constant SOFTWARE_SYSTEM_NAME \"Software System 2\"\n" +
372+
" !var SOFTWARE_SYSTEM_NAME \"Software System 2\"\n" +
373373
" softwareSystem \"${SOFTWARE_SYSTEM_NAME}\" {\n" +
374374
" !docs ../../docs\n" +
375375
" }\n" +
376376
"\n" +
377-
" !constant SOFTWARE_SYSTEM_NAME \"Software System 3\"\n" +
377+
" !var SOFTWARE_SYSTEM_NAME \"Software System 3\"\n" +
378378
" softwareSystem \"${SOFTWARE_SYSTEM_NAME}\" {\n" +
379379
" !docs ../../docs\n" +
380380
" }\n" +
@@ -1076,4 +1076,36 @@ void test_UnbalancedCurlyBraces() {
10761076
}
10771077
}
10781078

1079+
@Test
1080+
void test_Const() {
1081+
try {
1082+
StructurizrDslParser parser = new StructurizrDslParser();
1083+
parser.parse("""
1084+
workspace {
1085+
!const name value1
1086+
!const name value2
1087+
}
1088+
""");
1089+
fail();
1090+
} catch (StructurizrDslParserException e) {
1091+
assertEquals("A constant/variable \"name\" already exists at line 3: !const name value2", e.getMessage());
1092+
}
1093+
}
1094+
1095+
@Test
1096+
void test_Var_CannotOverrideConst() {
1097+
try {
1098+
StructurizrDslParser parser = new StructurizrDslParser();
1099+
parser.parse("""
1100+
workspace {
1101+
!const name value1
1102+
!var name value2
1103+
}
1104+
""");
1105+
fail();
1106+
} catch (StructurizrDslParserException e) {
1107+
assertEquals("A constant \"name\" already exists at line 3: !var name value2", e.getMessage());
1108+
}
1109+
}
1110+
10791111
}

0 commit comments

Comments
 (0)