diff --git a/extensions/arc/deployment/src/main/java/io/quarkus/arc/deployment/devconsole/ClassName.java b/extensions/arc/deployment/src/main/java/io/quarkus/arc/deployment/devconsole/ClassName.java deleted file mode 100644 index e25b632814bf9..0000000000000 --- a/extensions/arc/deployment/src/main/java/io/quarkus/arc/deployment/devconsole/ClassName.java +++ /dev/null @@ -1,29 +0,0 @@ -package io.quarkus.arc.deployment.devconsole; - -// FIXME: this should be a template extension method for String -public class ClassName { - private String name; - - public ClassName() { - } - - public ClassName(String name) { - this.name = name; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public String getLocalName() { - int lastDot = name.lastIndexOf('.'); - if (lastDot != -1) { - return name.substring(lastDot + 1); - } - return name; - } -} diff --git a/extensions/arc/deployment/src/main/java/io/quarkus/arc/deployment/devconsole/DevBeanInfo.java b/extensions/arc/deployment/src/main/java/io/quarkus/arc/deployment/devconsole/DevBeanInfo.java index f088c7c16aa7d..9650437659288 100644 --- a/extensions/arc/deployment/src/main/java/io/quarkus/arc/deployment/devconsole/DevBeanInfo.java +++ b/extensions/arc/deployment/src/main/java/io/quarkus/arc/deployment/devconsole/DevBeanInfo.java @@ -1,80 +1,127 @@ package io.quarkus.arc.deployment.devconsole; -import java.util.ArrayList; -import java.util.List; +import java.util.HashSet; +import java.util.Set; -public class DevBeanInfo implements Comparable { - - private ClassName name; - private String methodName; - private DevBeanKind kind; - private ClassName type; - private List qualifiers = new ArrayList<>(); - private ClassName scope; +import org.jboss.jandex.AnnotationInstance; +import org.jboss.jandex.AnnotationTarget; +import org.jboss.jandex.AnnotationTarget.Kind; +import org.jboss.jandex.ClassInfo; +import org.jboss.jandex.FieldInfo; +import org.jboss.jandex.MethodInfo; +import org.jboss.jandex.Type; - public DevBeanInfo() { - } +import io.quarkus.arc.deployment.CompletedApplicationClassPredicateBuildItem; +import io.quarkus.arc.processor.BeanInfo; +import io.quarkus.arc.processor.DotNames; - public DevBeanInfo(ClassName name, String methodName, ClassName type, List qualifiers, ClassName scope, - DevBeanKind kind) { - this.name = name; - this.methodName = methodName; - this.type = type; - this.qualifiers = qualifiers; - this.scope = scope; - this.kind = kind; - } +public class DevBeanInfo implements Comparable { - public void setKind(DevBeanKind kind) { - this.kind = kind; + private final DevBeanKind kind; + private final boolean isApplicationBean; + private final Name providerType; + private final String memberName; + private final Set types; + private final Set qualifiers; + private final Name scope; + private final Name declaringClass; + + public DevBeanInfo(BeanInfo bean, CompletedApplicationClassPredicateBuildItem predicate) { + qualifiers = new HashSet<>(); + for (AnnotationInstance qualifier : bean.getQualifiers()) { + qualifiers.add(Name.from(qualifier)); + } + scope = Name.from(bean.getScope().getDotName()); + types = new HashSet<>(); + for (Type beanType : bean.getTypes()) { + types.add(Name.from(beanType)); + } + + providerType = Name.from(bean.getProviderType()); + + if (bean.getTarget().isPresent()) { + AnnotationTarget target = bean.getTarget().get(); + if (target.kind() == Kind.METHOD) { + MethodInfo method = target.asMethod(); + memberName = method.name(); + this.kind = DevBeanKind.METHOD; + this.isApplicationBean = predicate.test(bean.getDeclaringBean().getBeanClass()); + this.declaringClass = Name.from(bean.getDeclaringBean().getBeanClass()); + } else if (target.kind() == Kind.FIELD) { + FieldInfo field = target.asField(); + this.memberName = field.name(); + this.kind = DevBeanKind.FIELD; + this.isApplicationBean = predicate.test(bean.getDeclaringBean().getBeanClass()); + this.declaringClass = Name.from(bean.getDeclaringBean().getBeanClass()); + } else if (target.kind() == Kind.CLASS) { + ClassInfo clazz = target.asClass(); + this.kind = DevBeanKind.CLASS; + this.memberName = null; + this.isApplicationBean = predicate.test(clazz.name()); + this.declaringClass = null; + } else { + throw new IllegalArgumentException("Invalid annotation target: " + target); + } + } else { + // Synthetic bean + this.kind = DevBeanKind.SYNTHETIC; + this.isApplicationBean = false; + this.declaringClass = null; + this.memberName = null; + } } public DevBeanKind getKind() { return kind; } - public void setScope(ClassName scope) { - this.scope = scope; - } - - public ClassName getScope() { + public Name getScope() { return scope; } - public List getQualifiers() { + public Set getQualifiers() { return qualifiers; } - public void setQualifiers(List qualifiers) { - this.qualifiers = qualifiers; - } - - public void setType(ClassName type) { - this.type = type; + public Set getNonDefaultQualifiers() { + Set nonDefault = new HashSet<>(); + String atDefault = DotNames.DEFAULT.toString(); + String atAny = DotNames.ANY.toString(); + for (Name qualifier : qualifiers) { + if (qualifier.toString().endsWith(atDefault) || qualifier.toString().endsWith(atAny)) { + continue; + } + nonDefault.add(qualifier); + } + return nonDefault; } - public ClassName getType() { - return type; + public Set getTypes() { + return types; } - public String getMethodName() { - return methodName; + public Name getProviderType() { + return providerType; } - public void setMethodName(String methodName) { - this.methodName = methodName; + public String getMemberName() { + return memberName; } - public void setName(ClassName name) { - this.name = name; + public boolean isApplicationBean() { + return isApplicationBean; } - public ClassName getName() { - return name; + public Name getDeclaringClass() { + return declaringClass; } @Override public int compareTo(DevBeanInfo o) { - return type.getLocalName().compareTo(o.type.getLocalName()); + // Application beans should go first + if (isApplicationBean == o.isApplicationBean) { + return providerType.compareTo(o.providerType); + } + return isApplicationBean ? -1 : 1; } } diff --git a/extensions/arc/deployment/src/main/java/io/quarkus/arc/deployment/devconsole/DevConsoleProcessor.java b/extensions/arc/deployment/src/main/java/io/quarkus/arc/deployment/devconsole/DevConsoleProcessor.java index c87ff32112c4c..3801d05cbc3ee 100644 --- a/extensions/arc/deployment/src/main/java/io/quarkus/arc/deployment/devconsole/DevConsoleProcessor.java +++ b/extensions/arc/deployment/src/main/java/io/quarkus/arc/deployment/devconsole/DevConsoleProcessor.java @@ -1,23 +1,17 @@ package io.quarkus.arc.deployment.devconsole; -import java.util.ArrayList; import java.util.HashSet; import java.util.List; -import java.util.Optional; import java.util.Set; -import org.jboss.jandex.AnnotationInstance; -import org.jboss.jandex.AnnotationTarget; -import org.jboss.jandex.AnnotationTarget.Kind; import org.jboss.jandex.ClassInfo; import org.jboss.jandex.DotName; -import org.jboss.jandex.FieldInfo; -import org.jboss.jandex.MethodInfo; import io.quarkus.arc.deployment.AdditionalBeanBuildItem; import io.quarkus.arc.deployment.AnnotationsTransformerBuildItem; import io.quarkus.arc.deployment.ArcConfig; import io.quarkus.arc.deployment.BeanDefiningAnnotationBuildItem; +import io.quarkus.arc.deployment.CompletedApplicationClassPredicateBuildItem; import io.quarkus.arc.deployment.CustomScopeAnnotationsBuildItem; import io.quarkus.arc.deployment.ValidationPhaseBuildItem; import io.quarkus.arc.processor.AnnotationsTransformer; @@ -94,74 +88,23 @@ public void transform(TransformationContext transformationContext) { } @BuildStep(onlyIf = IsDevelopment.class) - public DevConsoleTemplateInfoBuildItem collectBeanInfo(ValidationPhaseBuildItem validationPhaseBuildItem) { + public DevConsoleTemplateInfoBuildItem collectBeanInfo(ValidationPhaseBuildItem validationPhaseBuildItem, + CompletedApplicationClassPredicateBuildItem predicate) { BeanDeploymentValidator.ValidationContext validationContext = validationPhaseBuildItem.getContext(); DevBeanInfos beanInfos = new DevBeanInfos(); for (BeanInfo beanInfo : validationContext.beans()) { - beanInfos.addBean(createBeanInfo(beanInfo)); + beanInfos.addBean(new DevBeanInfo(beanInfo, predicate)); } for (BeanInfo beanInfo : validationContext.removedBeans()) { - beanInfos.addRemovedBean(createBeanInfo(beanInfo)); + beanInfos.addRemovedBean(new DevBeanInfo(beanInfo, predicate)); } for (ObserverInfo observerInfo : validationContext.get(BuildExtension.Key.OBSERVERS)) { - beanInfos.addObserver(createDevInfo(observerInfo)); + beanInfos.addObserver(new DevObserverInfo(observerInfo, predicate)); } + beanInfos.sort(); return new DevConsoleTemplateInfoBuildItem("devBeanInfos", beanInfos); } - private DevBeanInfo createBeanInfo(BeanInfo beanInfo) { - List qualifiers = new ArrayList<>(); - for (AnnotationInstance qualAnnotation : beanInfo.getQualifiers()) { - qualifiers.add(new ClassName(qualAnnotation.name().toString())); - } - ClassName scope = new ClassName(beanInfo.getScope().getDotName().toString()); - Optional target = beanInfo.getTarget(); - if (target.isPresent()) { - AnnotationTarget annotated = target.get(); - String methodName = null; - ClassName type = null; - ClassName providerClass = null; - DevBeanKind kind = null; - if (annotated.kind() == Kind.METHOD) { - MethodInfo method = annotated.asMethod(); - methodName = method.name(); - type = new ClassName(method.returnType().toString()); - providerClass = new ClassName(method.declaringClass().toString()); - kind = DevBeanKind.METHOD; - } else if (annotated.kind() == Kind.FIELD) { - FieldInfo field = annotated.asField(); - methodName = field.name(); - type = new ClassName(field.type().toString()); - providerClass = new ClassName(field.declaringClass().toString()); - kind = DevBeanKind.FIELD; - } else if (annotated.kind() == Kind.CLASS) { - ClassInfo klass = annotated.asClass(); - type = new ClassName(klass.name().toString()); - kind = DevBeanKind.CLASS; - } - return new DevBeanInfo(providerClass, methodName, type, qualifiers, scope, kind); - } else { - return new DevBeanInfo(null, null, new ClassName(beanInfo.getBeanClass().toString()), - qualifiers, - scope, DevBeanKind.SYNTHETIC); - } - } - - private DevObserverInfo createDevInfo(ObserverInfo observer) { - List qualifiers = new ArrayList<>(); - ClassName name = null; - String methodName = null; - for (AnnotationInstance qualAnnotation : observer.getQualifiers()) { - qualifiers.add(new ClassName(qualAnnotation.name().toString())); - } - if (observer.getDeclaringBean() != null) { - name = new ClassName(observer.getObserverMethod().declaringClass().name().toString()); - methodName = observer.getObserverMethod().name(); - } - return new DevObserverInfo(name, methodName, observer.getObservedType().toString(), qualifiers, observer.getPriority(), - observer.isAsync(), observer.getReception(), observer.getTransactionPhase()); - } - private boolean isAdditionalBeanDefiningAnnotationOn(ClassInfo beanClass, List beanDefiningAnnotations) { for (BeanDefiningAnnotationBuildItem beanDefiningAnnotation : beanDefiningAnnotations) { diff --git a/extensions/arc/deployment/src/main/java/io/quarkus/arc/deployment/devconsole/DevObserverInfo.java b/extensions/arc/deployment/src/main/java/io/quarkus/arc/deployment/devconsole/DevObserverInfo.java index 303a8f7af27a9..ea1fe066055b6 100644 --- a/extensions/arc/deployment/src/main/java/io/quarkus/arc/deployment/devconsole/DevObserverInfo.java +++ b/extensions/arc/deployment/src/main/java/io/quarkus/arc/deployment/devconsole/DevObserverInfo.java @@ -1,46 +1,63 @@ package io.quarkus.arc.deployment.devconsole; +import java.util.Collections; import java.util.List; +import java.util.stream.Collectors; import javax.enterprise.event.Reception; import javax.enterprise.event.TransactionPhase; +import io.quarkus.arc.deployment.CompletedApplicationClassPredicateBuildItem; +import io.quarkus.arc.processor.ObserverInfo; + public class DevObserverInfo implements Comparable { - private final ClassName name; + private final boolean isApplicationObserver; + private final Name declaringClass; private final String methodName; - private final String observedType; - private List qualifiers; + private final Name observedType; + private List qualifiers; private final int priority; private final boolean isAsync; private final Reception reception; private final TransactionPhase transactionPhase; - public DevObserverInfo(ClassName name, String methodInfo, String observedType, List qualifiers, int priority, - boolean isAsync, Reception reception, TransactionPhase transactionPhase) { - this.name = name; - this.methodName = methodInfo; - this.observedType = observedType; - this.qualifiers = qualifiers; - this.priority = priority; - this.isAsync = isAsync; - this.reception = reception; - this.transactionPhase = transactionPhase; + public DevObserverInfo(ObserverInfo observer, CompletedApplicationClassPredicateBuildItem predicate) { + priority = observer.getPriority(); + reception = observer.getReception(); + transactionPhase = observer.getTransactionPhase(); + isAsync = observer.isAsync(); + observedType = Name.from(observer.getObservedType()); + + if (observer.getQualifiers().isEmpty()) { + qualifiers = Collections.emptyList(); + } else { + qualifiers = observer.getQualifiers().stream().map(Name::from).collect(Collectors.toList()); + } + if (observer.getDeclaringBean() != null) { + declaringClass = Name.from(observer.getObserverMethod().declaringClass().name()); + methodName = observer.getObserverMethod().name(); + isApplicationObserver = predicate.test(observer.getObserverMethod().declaringClass().name()); + } else { + declaringClass = null; + methodName = null; + isApplicationObserver = false; + } } - public ClassName getName() { - return name; + public Name getDeclaringClass() { + return declaringClass; } public String getMethodName() { return methodName; } - public String getObservedType() { + public Name getObservedType() { return observedType; } - public List getQualifiers() { + public List getQualifiers() { return qualifiers; } @@ -60,14 +77,22 @@ public TransactionPhase getTransactionPhase() { return transactionPhase; } + public boolean isApplicationObserver() { + return isApplicationObserver; + } + @Override public int compareTo(DevObserverInfo o) { - if (name == null && o.name != null) { - return -1; - } else if (name != null && o.name == null) { - return 1; + // Application beans should go first + if (isApplicationObserver == o.isApplicationObserver) { + if (declaringClass == null && o.declaringClass != null) { + return -1; + } else if (declaringClass != null && o.declaringClass == null) { + return 1; + } + int ret = declaringClass.compareTo(o.declaringClass); + return ret == 0 ? methodName.compareTo(o.methodName) : ret; } - int ret = name.getLocalName().compareTo(o.name.getLocalName()); - return ret == 0 ? methodName.compareTo(o.methodName) : ret; + return isApplicationObserver ? -1 : 1; } } diff --git a/extensions/arc/deployment/src/main/java/io/quarkus/arc/deployment/devconsole/Name.java b/extensions/arc/deployment/src/main/java/io/quarkus/arc/deployment/devconsole/Name.java new file mode 100644 index 0000000000000..828c49f7ccb4e --- /dev/null +++ b/extensions/arc/deployment/src/main/java/io/quarkus/arc/deployment/devconsole/Name.java @@ -0,0 +1,112 @@ +package io.quarkus.arc.deployment.devconsole; + +import java.util.Iterator; +import java.util.List; +import java.util.Objects; + +import org.jboss.jandex.AnnotationInstance; +import org.jboss.jandex.AnnotationValue; +import org.jboss.jandex.DotName; +import org.jboss.jandex.ParameterizedType; +import org.jboss.jandex.Type; +import org.jboss.jandex.Type.Kind; + +public class Name implements Comparable { + + public static Name from(DotName dotName) { + return new Name(dotName.toString(), dotName.withoutPackagePrefix()); + } + + public static Name from(Type type) { + return new Name(type.toString(), createSimpleName(type)); + } + + public static Name from(AnnotationInstance annotation) { + return new Name(annotation.toString(false), createSimple(annotation)); + } + + private final String name; + private final String simpleName; + + private Name(String name, String simpleName) { + this.name = Objects.requireNonNull(name); + this.simpleName = simpleName; + } + + public Name(String name) { + this(name, null); + } + + public String getSimpleName() { + return simpleName != null ? simpleName : name; + } + + static String createSimpleName(Type type) { + switch (type.kind()) { + case CLASS: + return createSimple(type.name().toString()); + case PARAMETERIZED_TYPE: + return createSimple(type.asParameterizedType()); + case ARRAY: + Type component = type.asArrayType().component(); + if (component.kind() == Kind.CLASS) { + return createSimple(type.toString()); + } + default: + return null; + } + } + + static String createSimple(String name) { + int lastDot = name.lastIndexOf('.'); + if (lastDot != -1) { + return name.substring(lastDot + 1); + } + return name; + } + + static String createSimple(ParameterizedType parameterizedType) { + StringBuilder builder = new StringBuilder(); + builder.append(createSimple(parameterizedType.name().toString())); + List args = parameterizedType.arguments(); + if (!args.isEmpty()) { + builder.append('<'); + for (Iterator it = args.iterator(); it.hasNext();) { + builder.append(createSimpleName(it.next())); + if (it.hasNext()) { + builder.append(", "); + } + } + builder.append('>'); + } + return builder.toString(); + } + + static String createSimple(AnnotationInstance annotation) { + StringBuilder builder = new StringBuilder("@").append(createSimple(annotation.name().toString())); + List values = annotation.values(); + if (!values.isEmpty()) { + builder.append("("); + for (Iterator it = values.iterator(); it.hasNext();) { + builder.append(it.next()); + if (it.hasNext()) { + builder.append(","); + } + } + builder.append(')'); + } + + return builder.toString(); + } + + @Override + public int compareTo(Name other) { + return name.compareTo(other.name); + } + + @Override + public String toString() { + return name; + } + +} diff --git a/extensions/arc/deployment/src/main/resources/dev-templates/beans.html b/extensions/arc/deployment/src/main/resources/dev-templates/beans.html index 377730bb4c3fc..b2bab4ab06b86 100644 --- a/extensions/arc/deployment/src/main/resources/dev-templates/beans.html +++ b/extensions/arc/deployment/src/main/resources/dev-templates/beans.html @@ -2,6 +2,10 @@ {#style} .annotation { color: gray; + font-style: italic; + } + span.larger-badge { + font-size: 0.9em; } {/style} {#title}Beans{/title} @@ -11,7 +15,7 @@ # Bean - Source + Kind diff --git a/extensions/arc/deployment/src/main/resources/dev-templates/embedded.html b/extensions/arc/deployment/src/main/resources/dev-templates/embedded.html index bef53c49c182b..dd2fe654bde0d 100644 --- a/extensions/arc/deployment/src/main/resources/dev-templates/embedded.html +++ b/extensions/arc/deployment/src/main/resources/dev-templates/embedded.html @@ -18,8 +18,4 @@ {/if} - Removed Beans {info:arcContainer.removedBeans.size} -
- - - Interceptors {info:arcContainer.interceptors.size} + Removed Beans {info:arcContainer.removedBeans.size} \ No newline at end of file diff --git a/extensions/arc/deployment/src/main/resources/dev-templates/events.html b/extensions/arc/deployment/src/main/resources/dev-templates/events.html index d6f299f31f1e7..e7d62ddc3fda1 100644 --- a/extensions/arc/deployment/src/main/resources/dev-templates/events.html +++ b/extensions/arc/deployment/src/main/resources/dev-templates/events.html @@ -41,7 +41,7 @@ {event.timestamp} - {event.type} + {event.type} {#when event.qualifiers.size} diff --git a/extensions/arc/deployment/src/main/resources/dev-templates/invocations.html b/extensions/arc/deployment/src/main/resources/dev-templates/invocations.html index 0d5eff42e7e27..320bf44699109 100644 --- a/extensions/arc/deployment/src/main/resources/dev-templates/invocations.html +++ b/extensions/arc/deployment/src/main/resources/dev-templates/invocations.html @@ -33,6 +33,12 @@ ul code { color: #343a40; } + ul li { + margin-top: 5px; + } + span.declaring-class { + color: gray; + } {/style} {#script} var carets = document.getElementsByClassName("caret"); diff --git a/extensions/arc/deployment/src/main/resources/dev-templates/observers.html b/extensions/arc/deployment/src/main/resources/dev-templates/observers.html index 3827d0ab8de4c..b378d9a7f56bf 100644 --- a/extensions/arc/deployment/src/main/resources/dev-templates/observers.html +++ b/extensions/arc/deployment/src/main/resources/dev-templates/observers.html @@ -1,4 +1,13 @@ {#include main fluid=true} + {#style} + .annotation { + color: gray; + font-style: italic; + } + span.larger-badge { + font-size: 0.9em; + } + {/style} {#title}Observers{/title} {#body} @@ -18,14 +27,17 @@
{count}. - {#if observer.name != null} - {observer.name.localName}.{observer.methodName}() + {#if observer.declaringClass} + {observer.declaringClass}#{observer.methodName}() {#else} - Synthetic + Synthetic {/if} - {observer.observedType} + {#each observer.qualifiers} + {it.simpleName} + {/each} + {observer.observedType} {observer.priority} diff --git a/extensions/arc/deployment/src/main/resources/dev-templates/removed-beans.html b/extensions/arc/deployment/src/main/resources/dev-templates/removed-beans.html index b23303e1ab193..9cae8bf25ac30 100644 --- a/extensions/arc/deployment/src/main/resources/dev-templates/removed-beans.html +++ b/extensions/arc/deployment/src/main/resources/dev-templates/removed-beans.html @@ -2,6 +2,10 @@ {#style} .annotation { color: gray; + font-style: italic; + } + span.larger-badge { + font-size: 0.9em; } {/style} {#title}Removed Beans{/title} @@ -9,13 +13,15 @@ + - + {#for bean in info:devBeanInfos.removedBeans} + diff --git a/extensions/arc/deployment/src/main/resources/dev-templates/tags/bean-declaration.html b/extensions/arc/deployment/src/main/resources/dev-templates/tags/bean-declaration.html index c62639ff4fcd5..473affc152f1b 100644 --- a/extensions/arc/deployment/src/main/resources/dev-templates/tags/bean-declaration.html +++ b/extensions/arc/deployment/src/main/resources/dev-templates/tags/bean-declaration.html @@ -1,10 +1,10 @@ {#switch it.kind} {#case METHOD} - {it.name.localName}.{it.methodName}() + Producer method
{it.declaringClass.simpleName}.{it.memberName}() {#case FIELD} - {it.name.localName}.{it.methodName} + Producer field
{it.declaringClass.simpleName}.{it.memberName} {#case CLASS} - Class + Class {#else} - Synthetic + Synthetic {/switch} \ No newline at end of file diff --git a/extensions/arc/deployment/src/main/resources/dev-templates/tags/display-bean.html b/extensions/arc/deployment/src/main/resources/dev-templates/tags/display-bean.html index 2c9ae599b4f07..0358a27f24c61 100644 --- a/extensions/arc/deployment/src/main/resources/dev-templates/tags/display-bean.html +++ b/extensions/arc/deployment/src/main/resources/dev-templates/tags/display-bean.html @@ -1,7 +1,5 @@ -@{it.scope.localName}
-{#for qual in it.qualifiers} - {#if qual.name != 'javax.inject.Named' && qual.name != 'javax.enterprise.inject.Any' && qual.name != 'javax.enterprise.inject.Default'} - @{qual.localName}
- {/if} +@{it.scope.simpleName}
+{#for q in it.nonDefaultQualifiers} +{q.simpleName}
{/for} -{it.type.localName} +{it.providerType} diff --git a/extensions/arc/deployment/src/main/resources/dev-templates/tags/tree.html b/extensions/arc/deployment/src/main/resources/dev-templates/tags/tree.html index 1e645c938abef..211f0446aaa4f 100644 --- a/extensions/arc/deployment/src/main/resources/dev-templates/tags/tree.html +++ b/extensions/arc/deployment/src/main/resources/dev-templates/tags/tree.html @@ -3,13 +3,13 @@ {#if next}├─{#else}└─{/if} {/if} {#if it.children} -{it.methodInfo} {#duration it /}{#kind it /}{#if it.message != null} Error{/if} +{it.declaringClassName}#{it.method.name}() {#duration it /}{#kind it /}{#if it.message != null} Error{/if}
    {#each it.children} {#tree it root=false next=hasNext /} {/each}
{#else} -{it.methodInfo} {#duration it /}{#kind it /}{#if it.message != null} Error{/if} +{it.declaringClassName}#{it.method.name}() {#duration it /}{#kind it /}{#if it.message != null} Error{/if} {/if} \ No newline at end of file diff --git a/extensions/arc/deployment/src/test/java/io/quarkus/arc/test/devconsole/NameTest.java b/extensions/arc/deployment/src/test/java/io/quarkus/arc/test/devconsole/NameTest.java new file mode 100644 index 0000000000000..dba9292e95acc --- /dev/null +++ b/extensions/arc/deployment/src/test/java/io/quarkus/arc/test/devconsole/NameTest.java @@ -0,0 +1,67 @@ +package io.quarkus.arc.test.devconsole; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import org.jboss.jandex.AnnotationInstance; +import org.jboss.jandex.AnnotationValue; +import org.jboss.jandex.ArrayType; +import org.jboss.jandex.DotName; +import org.jboss.jandex.ParameterizedType; +import org.jboss.jandex.PrimitiveType; +import org.jboss.jandex.Type; +import org.jboss.jandex.Type.Kind; +import org.junit.jupiter.api.Test; + +import io.quarkus.arc.deployment.devconsole.Name; + +public class NameTest { + + @Test + public void testFromDotName() { + assertName(Name.from(DotName.createSimple("org.acme.Foo")), "org.acme.Foo", "Foo"); + assertName(Name.from(DotName.createSimple("org.acme.Foo$Lu")), "org.acme.Foo$Lu", "Foo$Lu"); + assertName(Name.from(PrimitiveType.BYTE.name()), "byte", "byte"); + } + + @Test + public void testFromType() { + assertName(Name.from(Type.create(DotName.createSimple("org.acme.Foo"), Kind.CLASS)), "org.acme.Foo", "Foo"); + assertName(Name.from(PrimitiveType.BOOLEAN), "boolean", "boolean"); + assertName(Name.from(ArrayType.create(PrimitiveType.LONG, 1)), "long[]", "long[]"); + assertName(Name.from(ArrayType.create(Type.create(DotName.createSimple("org.acme.Foo"), Kind.CLASS), 1)), + "org.acme.Foo[]", "Foo[]"); + assertName( + Name.from(ParameterizedType.create(DotName.createSimple("org.acme.Foo"), + new Type[] { Type.create(DotName.createSimple("java.lang.String"), Kind.CLASS) }, null)), + "org.acme.Foo", "Foo"); + assertName( + Name.from(ParameterizedType.create(DotName.createSimple("org.acme.Foo"), + new Type[] { ParameterizedType.create(DotName.createSimple("java.util.List"), + new Type[] { Type.create(DotName.createSimple("java.lang.String"), Kind.CLASS) }, null) }, + null)), + "org.acme.Foo>", "Foo>"); + } + + @Test + public void testFromAnnotation() { + assertName( + Name.from(AnnotationInstance.create(DotName.createSimple("org.acme.Bar"), null, + new AnnotationValue[] {})), + "@org.acme.Bar", "@Bar"); + assertName( + Name.from(AnnotationInstance.create(DotName.createSimple("org.acme.Bar"), null, + new AnnotationValue[] { AnnotationValue.createBooleanValue("checked", false) })), + "@org.acme.Bar(checked = false)", "@Bar(checked = false)"); + assertName( + Name.from(AnnotationInstance.create(DotName.createSimple("org.acme.Bar"), null, + new AnnotationValue[] { AnnotationValue.createClassValue("impl", + Type.create(DotName.createSimple("org.acme.Baz"), Kind.CLASS)) })), + "@org.acme.Bar(impl = org.acme.Baz)", "@Bar(impl = org.acme.Baz)"); + } + + private void assertName(Name name, String expectedName, String expectedSimpleName) { + assertEquals(expectedName, name.toString()); + assertEquals(expectedSimpleName, name.getSimpleName()); + } + +} diff --git a/extensions/arc/runtime/src/main/java/io/quarkus/arc/runtime/devconsole/Invocation.java b/extensions/arc/runtime/src/main/java/io/quarkus/arc/runtime/devconsole/Invocation.java index e39534089db59..0ef4947314283 100644 --- a/extensions/arc/runtime/src/main/java/io/quarkus/arc/runtime/devconsole/Invocation.java +++ b/extensions/arc/runtime/src/main/java/io/quarkus/arc/runtime/devconsole/Invocation.java @@ -64,8 +64,8 @@ public Method getMethod() { return method; } - public String getMethodInfo() { - return method.getDeclaringClass().getSimpleName() + "." + method.getName() + "()"; + public String getDeclaringClassName() { + return method.getDeclaringClass().getName(); } public List getChildren() { @@ -85,6 +85,14 @@ public String toString() { return kind + " invocation of " + method; } + public String getPackageName(String name) { + int lastDot = name.lastIndexOf('.'); + if (lastDot != -1) { + return name.substring(0, lastDot); + } + return ""; + } + public enum Kind { BUSINESS, diff --git a/extensions/vertx-http/deployment/src/main/java/io/quarkus/vertx/http/deployment/devmode/console/DevConsoleProcessor.java b/extensions/vertx-http/deployment/src/main/java/io/quarkus/vertx/http/deployment/devmode/console/DevConsoleProcessor.java index 727246f3ee6e2..5b4ef0870ea40 100644 --- a/extensions/vertx-http/deployment/src/main/java/io/quarkus/vertx/http/deployment/devmode/console/DevConsoleProcessor.java +++ b/extensions/vertx-http/deployment/src/main/java/io/quarkus/vertx/http/deployment/devmode/console/DevConsoleProcessor.java @@ -36,6 +36,7 @@ import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelInitializer; +import io.netty.handler.codec.http.HttpHeaderNames; import io.quarkus.bootstrap.classloading.QuarkusClassLoader; import io.quarkus.bootstrap.model.AppArtifact; import io.quarkus.builder.item.SimpleBuildItem; @@ -68,14 +69,18 @@ import io.quarkus.qute.NamespaceResolver; import io.quarkus.qute.RawString; import io.quarkus.qute.ReflectionValueResolver; +import io.quarkus.qute.ResultMapper; import io.quarkus.qute.Results; import io.quarkus.qute.Results.Result; +import io.quarkus.qute.TemplateException; import io.quarkus.qute.TemplateLocator; +import io.quarkus.qute.TemplateNode.Origin; import io.quarkus.qute.UserTagSectionHelper; import io.quarkus.qute.ValueResolver; import io.quarkus.qute.ValueResolvers; import io.quarkus.qute.Variant; import io.quarkus.runtime.RuntimeValue; +import io.quarkus.runtime.TemplateHtmlBuilder; import io.quarkus.vertx.http.deployment.NonApplicationRootPathBuildItem; import io.quarkus.vertx.http.deployment.RouteBuildItem; import io.quarkus.vertx.http.runtime.devmode.DevConsoleFilter; @@ -193,7 +198,11 @@ protected static void newRouter(Engine engine, Handler errorHandler = new Handler() { @Override public void handle(RoutingContext event) { - log.error("Dev console request failed ", event.failure()); + String message = "Dev console request failed"; + log.error(message, event.failure()); + event.response().headers().set(HttpHeaderNames.CONTENT_TYPE, "text/html; charset=utf-8"); + event.response().end( + new TemplateHtmlBuilder("Internal Server Error", message, message).stack(event.failure()).toString()); } }; router = Router.router(devConsoleVertx); @@ -381,6 +390,28 @@ private Engine buildEngine(List devTemplatePaths) { } builder.addLocator(id -> locateTemplate(id, templates)); + builder.addResultMapper(new ResultMapper() { + @Override + public int getPriority() { + // The priority must be higher than the one used for HtmlEscaper + return 10; + } + + @Override + public boolean appliesTo(Origin origin, Object result) { + return result.equals(Result.NOT_FOUND); + } + + @Override + public String map(Object result, Expression expression) { + Origin origin = expression.getOrigin(); + throw new TemplateException(origin, + String.format("Property not found in expression {%s} in template %s on line %s", + expression.toOriginalString(), + origin.getTemplateId(), origin.getLine())); + } + }); + Engine engine = builder.build(); // pre-load all templates diff --git a/extensions/vertx-http/deployment/src/main/resources/dev-static/css/dev-console.css b/extensions/vertx-http/deployment/src/main/resources/dev-static/css/dev-console.css index d3a5913dc3c22..776b92a310109 100644 --- a/extensions/vertx-http/deployment/src/main/resources/dev-static/css/dev-console.css +++ b/extensions/vertx-http/deployment/src/main/resources/dev-static/css/dev-console.css @@ -55,3 +55,7 @@ h1 { margin-bottom: 0.75em; } + +.package-name { + color: dimgray; +} diff --git a/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/BeanInfo.java b/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/BeanInfo.java index 24fc03cd7f540..e4db190374e42 100644 --- a/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/BeanInfo.java +++ b/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/BeanInfo.java @@ -204,7 +204,7 @@ BeanDeployment getDeployment() { return beanDeployment; } - Type getProviderType() { + public Type getProviderType() { return providerType; }
# BeanSourceKind
{count}. {#display-bean bean/}