diff --git a/docs/changelog.md b/docs/changelog.md index 26655cb..ed0e73d 100644 --- a/docs/changelog.md +++ b/docs/changelog.md @@ -7,6 +7,7 @@ - Fixes https://github.com/structurizr/dsl/issues/324 (Groups with no curly braces breaks diagrams). - Adds a way to set the character encoding used by the DSL parser (see https://github.com/structurizr/dsl/issues/338). - Fixes https://github.com/structurizr/dsl/issues/336 (Dynamic View does not allow !script tag). +- `!extend` can now be used instead of `!ref`. ## 1.32.0 (28th July 2023) diff --git a/src/main/java/com/structurizr/dsl/RefParser.java b/src/main/java/com/structurizr/dsl/RefParser.java index e882a6c..d9df9b1 100644 --- a/src/main/java/com/structurizr/dsl/RefParser.java +++ b/src/main/java/com/structurizr/dsl/RefParser.java @@ -1,12 +1,11 @@ package com.structurizr.dsl; -import com.structurizr.model.Element; import com.structurizr.model.ModelItem; import com.structurizr.model.StaticStructureElement; final class RefParser extends AbstractParser { - private static final String GRAMMAR = "!ref "; + private static final String GRAMMAR = "%s "; private final static int IDENTIFIER_INDEX = 1; @@ -14,11 +13,11 @@ ModelItem parse(DslContext context, Tokens tokens) { // !ref if (tokens.hasMoreThan(IDENTIFIER_INDEX)) { - throw new RuntimeException("Too many tokens, expected: " + GRAMMAR); + throw new RuntimeException("Too many tokens, expected: " + String.format(GRAMMAR, tokens.get(0))); } if (!tokens.includes(IDENTIFIER_INDEX)) { - throw new RuntimeException("Expected: " + GRAMMAR); + throw new RuntimeException("Expected: " + String.format(GRAMMAR, tokens.get(0))); } String s = tokens.get(IDENTIFIER_INDEX); @@ -36,7 +35,7 @@ ModelItem parse(DslContext context, Tokens tokens) { } if (modelItem == null) { - throw new RuntimeException("An element/relationship referenced by \"" + s + "\" could not be found"); + throw new RuntimeException("An element/relationship identified by \"" + s + "\" could not be found"); } if (context instanceof GroupableDslContext && modelItem instanceof StaticStructureElement) { diff --git a/src/main/java/com/structurizr/dsl/StructurizrDslParser.java b/src/main/java/com/structurizr/dsl/StructurizrDslParser.java index 874e6d7..c51e792 100644 --- a/src/main/java/com/structurizr/dsl/StructurizrDslParser.java +++ b/src/main/java/com/structurizr/dsl/StructurizrDslParser.java @@ -323,7 +323,7 @@ void parse(List lines, File dslFile) throws StructurizrDslParserExceptio registerIdentifier(identifier, relationship); - } else if (REF_TOKEN.equalsIgnoreCase(firstToken) && (inContext(ModelDslContext.class))) { + } else if ((REF_TOKEN.equalsIgnoreCase(firstToken) || EXTEND_TOKEN.equalsIgnoreCase(firstToken)) && (inContext(ModelDslContext.class))) { ModelItem modelItem = new RefParser().parse(getContext(), tokens.withoutContextStartToken()); if (shouldStartContext(tokens)) { diff --git a/src/main/java/com/structurizr/dsl/StructurizrDslTokens.java b/src/main/java/com/structurizr/dsl/StructurizrDslTokens.java index 3d76df6..814c24b 100644 --- a/src/main/java/com/structurizr/dsl/StructurizrDslTokens.java +++ b/src/main/java/com/structurizr/dsl/StructurizrDslTokens.java @@ -101,6 +101,7 @@ class StructurizrDslTokens { static final String IDENTIFIERS_TOKEN = "!identifiers"; static final String IMPLIED_RELATIONSHIPS_TOKEN = "!impliedRelationships"; static final String REF_TOKEN = "!ref"; + static final String EXTEND_TOKEN = "!extend"; static final String PLUGIN_TOKEN = "!plugin"; static final String SCRIPT_TOKEN = "!script"; diff --git a/src/test/dsl/extend/extend-workspace-from-json-file.dsl b/src/test/dsl/extend/extend-workspace-from-json-file.dsl index 753a572..06e3ffc 100644 --- a/src/test/dsl/extend/extend-workspace-from-json-file.dsl +++ b/src/test/dsl/extend/extend-workspace-from-json-file.dsl @@ -1,13 +1,13 @@ workspace extends workspace.json { model { - // !ref with DSL identifier - !ref softwareSystem1 { + // !extend with DSL identifier + !extend softwareSystem1 { webapp1 = container "Web Application 1" } - // !ref with canonical name - !ref "SoftwareSystem://Software System 1" { + // !extend with canonical name + !extend "SoftwareSystem://Software System 1" { webapp2 = container "Web Application 2" } diff --git a/src/test/dsl/extend/extend-workspace-from-json-url.dsl b/src/test/dsl/extend/extend-workspace-from-json-url.dsl index 045bbee..e849123 100644 --- a/src/test/dsl/extend/extend-workspace-from-json-url.dsl +++ b/src/test/dsl/extend/extend-workspace-from-json-url.dsl @@ -1,13 +1,13 @@ workspace extends https://raw.githubusercontent.com/structurizr/dsl/master/src/test/dsl/extend/workspace.json { model { - // !ref with DSL identifier - !ref softwareSystem1 { + // !extend with DSL identifier + !extend softwareSystem1 { webapp1 = container "Web Application 1" } - // !ref with canonical name - !ref "SoftwareSystem://Software System 1" { + // !extend with canonical name + !extend "SoftwareSystem://Software System 1" { webapp2 = container "Web Application 2" } diff --git a/src/test/java/com/structurizr/dsl/RefParserTests.java b/src/test/java/com/structurizr/dsl/RefParserTests.java index f38e730..10e0cf9 100644 --- a/src/test/java/com/structurizr/dsl/RefParserTests.java +++ b/src/test/java/com/structurizr/dsl/RefParserTests.java @@ -1,6 +1,5 @@ package com.structurizr.dsl; -import com.structurizr.model.Element; import com.structurizr.model.ModelItem; import com.structurizr.model.Person; import com.structurizr.model.Relationship; @@ -15,7 +14,7 @@ class RefParserTests extends AbstractTests { @Test void test_parse_ThrowsAnException_WhenThereAreTooManyTokens() { try { - parser.parse(context(), tokens("ref", "name", "tokens")); + parser.parse(context(), tokens("!ref", "name", "tokens")); fail(); } catch (Exception e) { assertEquals("Too many tokens, expected: !ref ", e.getMessage()); @@ -25,27 +24,27 @@ void test_parse_ThrowsAnException_WhenThereAreTooManyTokens() { @Test void test_parse_ThrowsAnException_WhenTheIdentifierOrCanonicalNameIsNotSpecified() { try { - parser.parse(context(), tokens("ref")); + parser.parse(context(), tokens("!extend")); fail(); } catch (Exception e) { - assertEquals("Expected: !ref ", e.getMessage()); + assertEquals("Expected: !extend ", e.getMessage()); } } @Test void test_parse_ThrowsAnException_WhenTheReferencedElementCannotBeFound() { try { - parser.parse(context(), tokens("ref", "Person://User")); + parser.parse(context(), tokens("!ref", "Person://User")); fail(); } catch (Exception e) { - assertEquals("An element/relationship referenced by \"Person://User\" could not be found", e.getMessage()); + assertEquals("An element/relationship identified by \"Person://User\" could not be found", e.getMessage()); } } @Test void test_parse_FindsAnElementByCanonicalName() { Person user = workspace.getModel().addPerson("User"); - ModelItem element = parser.parse(context(), tokens("ref", "Person://User")); + ModelItem element = parser.parse(context(), tokens("!ref", "Person://User")); assertSame(user, element); } @@ -59,7 +58,7 @@ void test_parse_FindsAnElementByIdentifier() { register.register("user", user); context.setIdentifierRegister(register); - ModelItem modelItem = parser.parse(context, tokens("ref", "user")); + ModelItem modelItem = parser.parse(context, tokens("!ref", "user")); assertSame(modelItem, user); } @@ -73,7 +72,7 @@ void test_parse_FindsARelationshipByIdentifier() { register.register("rel", relationship); context.setIdentifierRegister(register); - ModelItem modelItem = parser.parse(context, tokens("ref", "rel")); + ModelItem modelItem = parser.parse(context, tokens("!ref", "rel")); assertSame(modelItem, relationship); }