Skip to content

Commit

Permalink
Merge pull request #1464 from scireum/feature/ool/SE-13618
Browse files Browse the repository at this point in the history
SE-13618: Extend the checks of the TemplateCompiler to include missing required attributes
  • Loading branch information
oolscireum authored Oct 2, 2024
2 parents 32449d3 + 78a8a23 commit 7f82e9e
Show file tree
Hide file tree
Showing 18 changed files with 155 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,14 @@

package sirius.pasta.tagliatelle.compiler;

import sirius.kernel.tokenizer.Char;
import sirius.kernel.tokenizer.ParseError;
import sirius.kernel.tokenizer.Position;
import sirius.kernel.commons.Explain;
import sirius.kernel.commons.Strings;
import sirius.kernel.di.std.PriorityParts;
import sirius.kernel.health.Exceptions;
import sirius.kernel.health.HandledException;
import sirius.kernel.tokenizer.Char;
import sirius.kernel.tokenizer.ParseError;
import sirius.kernel.tokenizer.Position;
import sirius.pasta.Pasta;
import sirius.pasta.noodle.Callable;
import sirius.pasta.noodle.ConstantCall;
Expand All @@ -33,7 +33,10 @@

import javax.annotation.Nullable;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.function.Predicate;

/**
* Compiles a sources file into a {@link sirius.pasta.tagliatelle.Template}.
Expand Down Expand Up @@ -369,6 +372,8 @@ private void handleTag(TagHandler handler, CompositeEmitter block) {
* @param handler the handler to add the attributes to
*/
private void parseAttributes(TagHandler handler) {
// Collect all parsed attributes.
Set<String> attributes = new HashSet<>();
while (true) {
skipWhitespaces();
if (reader.current().isEndOfInput() || reader.current().is('>', '/')) {
Expand All @@ -379,6 +384,10 @@ private void parseAttributes(TagHandler handler) {
verifyAttributeNameAndType(handler, name, attributeType);
if (attributeType == null) {
attributeType = String.class;
} else {
// verifyAttributeNameAndType(...) already reports an error if the attributeType is unknown.
// We only save the found and defined attributes.
attributes.add(name);
}

skipWhitespaces();
Expand Down Expand Up @@ -417,6 +426,24 @@ private void parseAttributes(TagHandler handler) {
}
consumeExpectedCharacter('"');
}

checkMissingAttributes(handler, attributes);
}

/**
* Checks if all required attributes are present.
*
* @param handler the tag handler
* @param attributes the set of attributes which were parsed
*/
private void checkMissingAttributes(TagHandler handler, Set<String> attributes) {
handler.getRequiredAttributeNames()
.stream()
.filter(Predicate.not(attributes::contains))
.forEach(attr -> context.error(reader.current(),
"Missing required attribute. %s missing the required attribute '%s'.",
handler.getTagName(),
attr));
}

private void parseAttributeExpression(TagHandler handler,
Expand Down
6 changes: 6 additions & 0 deletions src/main/java/sirius/pasta/tagliatelle/tags/ArgTag.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import javax.annotation.Nonnull;
import java.util.Arrays;
import java.util.List;
import java.util.Set;

/**
* Handles <tt>i:arg</tt> which specifies a template argument.
Expand Down Expand Up @@ -157,4 +158,9 @@ public Class<?> getExpectedAttributeType(String name) {

return super.getExpectedAttributeType(name);
}

@Override
public Set<String> getRequiredAttributeNames() {
return Set.of(PARAM_NAME, PARAM_TYPE);
}
}
6 changes: 6 additions & 0 deletions src/main/java/sirius/pasta/tagliatelle/tags/BlockTag.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.Set;

/**
* Handles <tt>i:block</tt> which specifies a template section passed into a tag invocation.
Expand Down Expand Up @@ -85,4 +86,9 @@ public Class<?> getExpectedAttributeType(String name) {

return super.getExpectedAttributeType(name);
}

@Override
public Set<String> getRequiredAttributeNames() {
return Set.of(PARAM_NAME);
}
}
6 changes: 6 additions & 0 deletions src/main/java/sirius/pasta/tagliatelle/tags/DefineTag.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import javax.annotation.Nonnull;
import java.util.Collections;
import java.util.List;
import java.util.Set;

/**
* Handles <tt>i:define</tt> which defines a string as the evaluation result of its body.
Expand Down Expand Up @@ -81,4 +82,9 @@ public Class<?> getExpectedAttributeType(String name) {

return super.getExpectedAttributeType(name);
}

@Override
public Set<String> getRequiredAttributeNames() {
return Set.of(PARAM_NAME);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import javax.annotation.Nonnull;
import java.util.Collections;
import java.util.List;
import java.util.Set;

/**
* Handles <tt>i:dynamicInvoke</tt> which invokes or inlines a given template.
Expand Down Expand Up @@ -69,4 +70,9 @@ public Class<?> getExpectedAttributeType(String name) {
// Accept anything, we don't know yet what to expect at runtime....
return Callable.class;
}

@Override
public Set<String> getRequiredAttributeNames() {
return Set.of(ATTR_TEMPLATE);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import javax.annotation.Nonnull;
import java.util.Collections;
import java.util.List;
import java.util.Set;

/**
* Handles <tt>i:extensions</tt> which invokes all extensions with the given name.
Expand Down Expand Up @@ -86,4 +87,9 @@ public Class<?> getExpectedAttributeType(String name) {

return Callable.class;
}

@Override
public Set<String> getRequiredAttributeNames() {
return Set.of(ATTR_TARGET);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import javax.annotation.Nonnull;
import java.util.Collections;
import java.util.List;
import java.util.Set;

/**
* Permits to add an extra block to the global render context.
Expand Down Expand Up @@ -86,4 +87,9 @@ public Class<?> getExpectedAttributeType(String name) {

return super.getExpectedAttributeType(name);
}

@Override
public Set<String> getRequiredAttributeNames() {
return Set.of(PARAM_NAME);
}
}
6 changes: 6 additions & 0 deletions src/main/java/sirius/pasta/tagliatelle/tags/ForTag.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import javax.annotation.Nonnull;
import java.util.Arrays;
import java.util.List;
import java.util.Set;

/**
* Handles <tt>i:for</tt> which emits its body for each item in an {@link Iterable}.
Expand Down Expand Up @@ -116,4 +117,9 @@ public Class<?> getExpectedAttributeType(String name) {

return super.getExpectedAttributeType(name);
}

@Override
public Set<String> getRequiredAttributeNames() {
return Set.of(PARAM_ITEMS, PARAM_TYPE, PARAM_VAR);
}
}
6 changes: 6 additions & 0 deletions src/main/java/sirius/pasta/tagliatelle/tags/IfTag.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import javax.annotation.Nonnull;
import java.util.Collections;
import java.util.List;
import java.util.Set;

/**
* Handles <tt>i:if</tt> which emits its body if a condition is met.
Expand Down Expand Up @@ -71,4 +72,9 @@ public Class<?> getExpectedAttributeType(String name) {

return super.getExpectedAttributeType(name);
}

@Override
public Set<String> getRequiredAttributeNames() {
return Set.of("test");
}
}
6 changes: 6 additions & 0 deletions src/main/java/sirius/pasta/tagliatelle/tags/IncludeTag.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import javax.annotation.Nonnull;
import java.util.Collections;
import java.util.List;
import java.util.Set;

/**
* Handles <tt>i:include</tt> which includes the contents of the given resource without any processing.
Expand Down Expand Up @@ -74,4 +75,9 @@ public Class<?> getExpectedAttributeType(String name) {

return super.getExpectedAttributeType(name);
}

@Override
public Set<String> getRequiredAttributeNames() {
return Set.of(ATTR_NAME);
}
}
17 changes: 17 additions & 0 deletions src/main/java/sirius/pasta/tagliatelle/tags/InvokeTag.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@

import javax.annotation.Nonnull;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
* Handles <tt>i:invoke</tt> which invokes or inlines a given template.
Expand Down Expand Up @@ -116,6 +118,21 @@ public Class<?> getExpectedAttributeType(String name) {
}
}

@Override
public Set<String> getRequiredAttributeNames() {
Set<String> result = new HashSet<>();
result.add(ATTR_TEMPLATE);

if (ensureThatTemplateIsPresent()) {
for (TemplateArgument arg : template.getArguments()) {
if (arg.getDefaultValue() == null) {
result.add(arg.getName());
}
}
}
return result;
}

private boolean ensureThatTemplateIsPresent() {
if (template == null) {
if (templateResolved) {
Expand Down
6 changes: 6 additions & 0 deletions src/main/java/sirius/pasta/tagliatelle/tags/LocalTag.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import javax.annotation.Nonnull;
import java.util.Arrays;
import java.util.List;
import java.util.Set;

/**
* Handles <tt>i:local</tt> which defines a local variable.
Expand Down Expand Up @@ -92,4 +93,9 @@ public Class<?> getExpectedAttributeType(String name) {

return super.getExpectedAttributeType(name);
}

@Override
public Set<String> getRequiredAttributeNames() {
return Set.of(PARAM_NAME, PARAM_VALUE);
}
}
6 changes: 6 additions & 0 deletions src/main/java/sirius/pasta/tagliatelle/tags/PragmaTag.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import javax.annotation.Nonnull;
import java.util.Arrays;
import java.util.List;
import java.util.Set;

/**
* Handles <tt>i:pragma</tt> which defines a pragma (key / value pair) for a template.
Expand Down Expand Up @@ -79,4 +80,9 @@ public Class<?> getExpectedAttributeType(String name) {

return super.getExpectedAttributeType(name);
}

@Override
public Set<String> getRequiredAttributeNames() {
return Set.of(PARAM_NAME);
}
}
6 changes: 6 additions & 0 deletions src/main/java/sirius/pasta/tagliatelle/tags/RenderTag.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import javax.annotation.Nonnull;
import java.util.Collections;
import java.util.List;
import java.util.Set;

/**
* Handles <tt>i:render</tt> which emits the block with the given name.
Expand Down Expand Up @@ -79,4 +80,9 @@ public Class<?> getExpectedAttributeType(String name) {

return super.getExpectedAttributeType(name);
}

@Override
public Set<String> getRequiredAttributeNames() {
return Set.of(PARAM_NAME);
}
}
6 changes: 6 additions & 0 deletions src/main/java/sirius/pasta/tagliatelle/tags/SassTag.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import java.io.StringReader;
import java.util.Collections;
import java.util.List;
import java.util.Set;

/**
* Handles <tt>i:sass</tt> which renders a SASS file into the current template as compiled CSS.
Expand Down Expand Up @@ -93,4 +94,9 @@ public Class<?> getExpectedAttributeType(String name) {

return super.getExpectedAttributeType(name);
}

@Override
public Set<String> getRequiredAttributeNames() {
return Set.of(SOURCE_ATTRIBUTE);
}
}
6 changes: 6 additions & 0 deletions src/main/java/sirius/pasta/tagliatelle/tags/SwitchTag.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import javax.annotation.Nonnull;
import java.util.Collections;
import java.util.List;
import java.util.Set;

/**
* Handles <tt>i:switch</tt> which can hold multiple blocks which are only rendered if their name matches an expression.
Expand Down Expand Up @@ -68,4 +69,9 @@ public Class<?> getExpectedAttributeType(String name) {

return super.getExpectedAttributeType(name);
}

@Override
public Set<String> getRequiredAttributeNames() {
return Set.of("test");
}
}
10 changes: 10 additions & 0 deletions src/main/java/sirius/pasta/tagliatelle/tags/TagHandler.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,11 @@

import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import java.util.Set;

/**
* Handles a tag detected by the {@link sirius.pasta.tagliatelle.compiler.TemplateCompiler}.
Expand Down Expand Up @@ -93,6 +95,14 @@ public Callable getAttribute(String name) {
return attributes.get(name);
}

/**
* Returns all required attribute names.
* @return a set of all attribute names.
*/
public Set<String> getRequiredAttributeNames() {
return Collections.emptySet();
}

/**
* Fetches the attribute with the given name, expecting that a constant value is present.
*
Expand Down
Loading

0 comments on commit 7f82e9e

Please sign in to comment.