• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

raphw / byte-buddy / #801

27 Oct 2025 09:37AM UTC coverage: 84.715% (-0.4%) from 85.118%
#801

push

raphw
Fix imports.

29586 of 34924 relevant lines covered (84.72%)

0.85 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

88.89
/byte-buddy-dep/src/main/java/net/bytebuddy/build/ToStringPlugin.java
1
/*
2
 * Copyright 2014 - Present Rafael Winterhalter
3
 *
4
 * Licensed under the Apache License, Version 2.0 (the "License");
5
 * you may not use this file except in compliance with the License.
6
 * You may obtain a copy of the License at
7
 *
8
 *     http://www.apache.org/licenses/LICENSE-2.0
9
 *
10
 * Unless required by applicable law or agreed to in writing, software
11
 * distributed under the License is distributed on an "AS IS" BASIS,
12
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
 * See the License for the specific language governing permissions and
14
 * limitations under the License.
15
 */
16
package net.bytebuddy.build;
17

18
import net.bytebuddy.description.annotation.AnnotationDescription;
19
import net.bytebuddy.description.field.FieldDescription;
20
import net.bytebuddy.description.method.MethodDescription;
21
import net.bytebuddy.description.method.MethodList;
22
import net.bytebuddy.description.type.TypeDescription;
23
import net.bytebuddy.dynamic.ClassFileLocator;
24
import net.bytebuddy.dynamic.DynamicType;
25
import net.bytebuddy.implementation.ToStringMethod;
26
import net.bytebuddy.matcher.ElementMatchers;
27
import net.bytebuddy.utility.nullability.MaybeNull;
28

29
import java.lang.annotation.Documented;
30
import java.lang.annotation.ElementType;
31
import java.lang.annotation.Retention;
32
import java.lang.annotation.RetentionPolicy;
33
import java.lang.annotation.Target;
34

35
import static net.bytebuddy.matcher.ElementMatchers.isAnnotatedWith;
36
import static net.bytebuddy.matcher.ElementMatchers.isToString;
37
import static net.bytebuddy.matcher.ElementMatchers.named;
38

39
/**
40
 * A build tool plugin that adds a {@link Object#toString()} and method to a class if the {@link Enhance} annotation is present and no
41
 * explicit method declaration was added. This plugin does not need to be closed.
42
 */
43
@HashCodeAndEqualsPlugin.Enhance
44
public class ToStringPlugin implements Plugin, Plugin.Factory {
1✔
45

46
    /**
47
     * A description of the {@link Enhance#prefix()} method.
48
     */
49
    private static final MethodDescription.InDefinedShape ENHANCE_PREFIX;
50

51
    /**
52
     * A description of the {@link Enhance#includeSyntheticFields()} method.
53
     */
54
    private static final MethodDescription.InDefinedShape ENHANCE_INCLUDE_SYNTHETIC_FIELDS;
55

56
    /*
57
     * Resolves annotation properties.
58
     */
59
    static {
60
        MethodList<MethodDescription.InDefinedShape> enhanceMethods = TypeDescription.ForLoadedType.of(Enhance.class).getDeclaredMethods();
1✔
61
        ENHANCE_PREFIX = enhanceMethods.filter(named("prefix")).getOnly();
1✔
62
        ENHANCE_INCLUDE_SYNTHETIC_FIELDS = enhanceMethods.filter(named("includeSyntheticFields")).getOnly();
1✔
63
    }
1✔
64

65
    /**
66
     * {@inheritDoc}
67
     */
68
    public Plugin make() {
69
        return this;
×
70
    }
71

72
    /**
73
     * {@inheritDoc}
74
     */
75
    public boolean matches(@MaybeNull TypeDescription target) {
76
        return target != null && target.getDeclaredAnnotations().isAnnotationPresent(Enhance.class);
1✔
77
    }
78

79
    /**
80
     * {@inheritDoc}
81
     */
82
    public DynamicType.Builder<?> apply(DynamicType.Builder<?> builder, TypeDescription typeDescription, ClassFileLocator classFileLocator) {
83
        AnnotationDescription.Loadable<Enhance> enhance = typeDescription.getDeclaredAnnotations().ofType(Enhance.class);
1✔
84
        if (typeDescription.getDeclaredMethods().filter(isToString()).isEmpty()) {
1✔
85
            builder = builder.method(isToString()).intercept(ToStringMethod.prefixedBy(enhance.getValue(ENHANCE_PREFIX)
1✔
86
                            .load(Enhance.class.getClassLoader())
1✔
87
                            .resolve(Enhance.Prefix.class)
1✔
88
                            .getPrefixResolver())
1✔
89
                    .withIgnoredFields(enhance.getValue(ENHANCE_INCLUDE_SYNTHETIC_FIELDS).resolve(Boolean.class)
1✔
90
                            ? ElementMatchers.<FieldDescription>none()
×
91
                            : ElementMatchers.<FieldDescription>isSynthetic())
1✔
92
                    .withIgnoredFields(isAnnotatedWith(Exclude.class)));
1✔
93
        }
94
        return builder;
1✔
95
    }
96

97
    /**
98
     * {@inheritDoc}
99
     */
100
    public void close() {
101
        /* do nothing */
102
    }
×
103

104
    /**
105
     * Instructs the {@link ToStringPlugin} to generate a {@link Object#toString()} method for the annotated class unless this method
106
     * is already declared explicitly.
107
     */
108
    @Documented
109
    @Target(ElementType.TYPE)
110
    @Retention(RetentionPolicy.RUNTIME)
111
    public @interface Enhance {
112

113
        /**
114
         * Determines the prefix to be used for the string representation prior to adding field values.
115
         *
116
         * @return The prefix to use.
117
         */
118
        Prefix prefix() default Prefix.SIMPLE;
119

120
        /**
121
         * Determines if synthetic fields should be included in the string representation.
122
         *
123
         * @return {@code true} if synthetic fields should be included.
124
         */
125
        boolean includeSyntheticFields() default false;
126

127
        /**
128
         * A strategy for defining a prefix.
129
         */
130
        enum Prefix {
1✔
131

132
            /**
133
             * Determines the use of a fully qualified class name as a prefix.
134
             */
135
            FULLY_QUALIFIED(ToStringMethod.PrefixResolver.Default.FULLY_QUALIFIED_CLASS_NAME),
1✔
136

137
            /**
138
             * Determines the use of the canonical class name as a prefix.
139
             */
140
            CANONICAL(ToStringMethod.PrefixResolver.Default.CANONICAL_CLASS_NAME),
1✔
141

142
            /**
143
             * Determines the use of the simple class name as a prefix.
144
             */
145
            SIMPLE(ToStringMethod.PrefixResolver.Default.SIMPLE_CLASS_NAME);
1✔
146

147
            /**
148
             * The prefix resolver to use.
149
             */
150
            private final ToStringMethod.PrefixResolver.Default prefixResolver;
151

152
            /**
153
             * Creates a new prefix.
154
             *
155
             * @param prefixResolver The prefix resolver to use.
156
             */
157
            Prefix(ToStringMethod.PrefixResolver.Default prefixResolver) {
1✔
158
                this.prefixResolver = prefixResolver;
1✔
159
            }
1✔
160

161
            /**
162
             * Returns the prefix resolver to use.
163
             *
164
             * @return The prefix resolver to use.
165
             */
166
            protected ToStringMethod.PrefixResolver.Default getPrefixResolver() {
167
                return prefixResolver;
1✔
168
            }
169
        }
170
    }
171

172
    /**
173
     * Determines that the annotated field is excluded from a string representation of the {@link ToStringPlugin}.
174
     */
175
    @Documented
176
    @Target(ElementType.FIELD)
177
    @Retention(RetentionPolicy.RUNTIME)
178
    public @interface Exclude {
179
        /* does not declare any properties */
180
    }
181
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc