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

hazendaz / jmockit1 / 496

15 Nov 2025 05:33PM UTC coverage: 72.192% (-0.008%) from 72.2%
496

push

github

web-flow
Merge pull request #412 from hazendaz/renovate/major-spring-core

Update spring core to v7 (major)

5677 of 8360 branches covered (67.91%)

Branch coverage included in aggregate %.

11922 of 16018 relevant lines covered (74.43%)

0.74 hits per line

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

0.0
/main/src/main/java/mockit/coverage/modification/CoverageModifier.java
1
/*
2
 * MIT License
3
 * Copyright (c) 2006-2025 JMockit developers
4
 * See LICENSE file for full license text.
5
 */
6
package mockit.coverage.modification;
7

8
import static mockit.asm.jvmConstants.Access.ABSTRACT;
9
import static mockit.asm.jvmConstants.Access.ANNOTATION;
10
import static mockit.asm.jvmConstants.Access.ENUM;
11
import static mockit.asm.jvmConstants.Access.FINAL;
12
import static mockit.asm.jvmConstants.Access.INTERFACE;
13
import static mockit.asm.jvmConstants.Access.STATIC;
14
import static mockit.asm.jvmConstants.Access.SUPER;
15
import static mockit.asm.jvmConstants.Access.SYNTHETIC;
16

17
import edu.umd.cs.findbugs.annotations.NonNull;
18
import edu.umd.cs.findbugs.annotations.Nullable;
19

20
import java.util.HashMap;
21
import java.util.Map;
22

23
import mockit.asm.classes.ClassInfo;
24
import mockit.asm.classes.ClassReader;
25
import mockit.asm.classes.ClassWriter;
26
import mockit.asm.classes.WrappingClassVisitor;
27
import mockit.asm.fields.FieldVisitor;
28
import mockit.asm.methods.MethodVisitor;
29
import mockit.asm.methods.MethodWriter;
30
import mockit.coverage.data.CoverageData;
31
import mockit.coverage.data.FileCoverageData;
32
import mockit.internal.ClassFile;
33

34
final class CoverageModifier extends WrappingClassVisitor {
35
    private static final Map<String, CoverageModifier> INNER_CLASS_MODIFIERS = new HashMap<>();
×
36
    private static final int FIELD_MODIFIERS_TO_IGNORE = FINAL + SYNTHETIC;
37

38
    @Nullable
39
    static byte[] recoverModifiedByteCodeIfAvailable(@NonNull String innerClassName) {
40
        CoverageModifier modifier = INNER_CLASS_MODIFIERS.remove(innerClassName);
×
41
        return modifier == null ? null : modifier.toByteArray();
×
42
    }
43

44
    @Nullable
45
    private String internalClassName;
46
    @Nullable
47
    private String simpleClassName;
48
    @NonNull
49
    private String sourceFileName;
50
    @Nullable
51
    private FileCoverageData fileData;
52
    private final boolean forInnerClass;
53
    private boolean forEnumClass;
54
    @Nullable
55
    private String kindOfTopLevelType;
56

57
    CoverageModifier(@NonNull ClassReader cr) {
58
        this(cr, false);
×
59
    }
×
60

61
    private CoverageModifier(@NonNull ClassReader cr, boolean forInnerClass) {
62
        super(new ClassWriter(cr));
×
63
        sourceFileName = "";
×
64
        this.forInnerClass = forInnerClass;
×
65
    }
×
66

67
    private CoverageModifier(@NonNull ClassReader cr, @NonNull CoverageModifier other,
68
            @Nullable String simpleClassName) {
69
        this(cr, true);
×
70
        sourceFileName = other.sourceFileName;
×
71
        fileData = other.fileData;
×
72
        internalClassName = other.internalClassName;
×
73
        this.simpleClassName = simpleClassName;
×
74
    }
×
75

76
    @Override
77
    public void visit(int version, int access, @NonNull String name, @NonNull ClassInfo additionalInfo) {
78
        if ((access & SYNTHETIC) != 0) {
×
79
            throw new VisitInterruptedException();
×
80
        }
81

82
        boolean nestedType = name.indexOf('$') > 0;
×
83

84
        if (!nestedType && kindOfTopLevelType == null) {
×
85
            // noinspection ConstantConditions
86
            kindOfTopLevelType = getKindOfJavaType(access, additionalInfo.superName);
×
87
        }
88

89
        forEnumClass = (access & ENUM) != 0;
×
90

91
        String sourceFileDebugName = getSourceFileDebugName(additionalInfo);
×
92

93
        if (!forInnerClass) {
×
94
            extractClassAndSourceFileName(name);
×
95

96
            boolean cannotModify = (access & ANNOTATION) != 0;
×
97

98
            if (cannotModify) {
×
99
                throw VisitInterruptedException.INSTANCE;
×
100
            }
101

102
            registerAsInnerClassModifierIfApplicable(access, name, nestedType);
×
103
            createFileData(sourceFileDebugName);
×
104
        }
105

106
        cw.visit(version, access, name, additionalInfo);
×
107
    }
×
108

109
    @NonNull
110
    private static String getKindOfJavaType(int typeModifiers, @NonNull String superName) {
111
        if ((typeModifiers & ANNOTATION) != 0) {
×
112
            return "ant";
×
113
        }
114
        if ((typeModifiers & INTERFACE) != 0) {
×
115
            return "itf";
×
116
        }
117
        if ((typeModifiers & ENUM) != 0) {
×
118
            return "enm";
×
119
        }
120
        if ((typeModifiers & ABSTRACT) != 0) {
×
121
            return "absCls";
×
122
        }
123
        if (superName.endsWith("Exception") || superName.endsWith("Error")) {
×
124
            return "exc";
×
125
        }
126
        return "cls";
×
127
    }
128

129
    @NonNull
130
    private static String getSourceFileDebugName(@NonNull ClassInfo additionalInfo) {
131
        String sourceFileDebugName = additionalInfo.sourceFileName;
×
132

133
        if (sourceFileDebugName == null || !sourceFileDebugName.endsWith(".java")) {
×
134
            throw VisitInterruptedException.INSTANCE;
×
135
        }
136

137
        return sourceFileDebugName;
×
138
    }
139

140
    private void extractClassAndSourceFileName(@NonNull String className) {
141
        internalClassName = className;
×
142
        int p = className.lastIndexOf('/');
×
143

144
        if (p < 0) {
×
145
            simpleClassName = className;
×
146
            sourceFileName = "";
×
147
        } else {
148
            simpleClassName = className.substring(p + 1);
×
149
            sourceFileName = className.substring(0, p + 1);
×
150
        }
151
    }
×
152

153
    private void registerAsInnerClassModifierIfApplicable(int access, @NonNull String name, boolean nestedType) {
154
        if (!forEnumClass && (access & SUPER) != 0 && nestedType) {
×
155
            INNER_CLASS_MODIFIERS.put(name.replace('/', '.'), this);
×
156
        }
157
    }
×
158

159
    private void createFileData(@NonNull String sourceFileDebugName) {
160
        sourceFileName += sourceFileDebugName;
×
161
        fileData = CoverageData.instance().getOrAddFile(sourceFileName, kindOfTopLevelType);
×
162
    }
×
163

164
    @Override
165
    public void visitInnerClass(@NonNull String name, @Nullable String outerName, @Nullable String innerName,
166
            int access) {
167
        cw.visitInnerClass(name, outerName, innerName, access);
×
168

169
        if (forInnerClass || isSyntheticOrEnumClass(access) || !isNestedInsideClassBeingModified(name, outerName)) {
×
170
            return;
×
171
        }
172

173
        String innerClassName = name.replace('/', '.');
×
174

175
        if (INNER_CLASS_MODIFIERS.containsKey(innerClassName)) {
×
176
            return;
×
177
        }
178

179
        ClassReader innerCR = ClassFile.createClassReader(CoverageModifier.class.getClassLoader(), name);
×
180

181
        if (innerCR != null) {
×
182
            CoverageModifier innerClassModifier = new CoverageModifier(innerCR, this, innerName);
×
183
            innerCR.accept(innerClassModifier);
×
184
            INNER_CLASS_MODIFIERS.put(innerClassName, innerClassModifier);
×
185
        }
186
    }
×
187

188
    private static boolean isSyntheticOrEnumClass(int access) {
189
        return (access & SYNTHETIC) != 0 || access == STATIC + ENUM;
×
190
    }
191

192
    private boolean isNestedInsideClassBeingModified(@NonNull String internalName, @Nullable String outerName) {
193
        String className = outerName == null ? internalName : outerName;
×
194
        int p = className.indexOf('$');
×
195
        String outerClassName = p < 0 ? className : className.substring(0, p);
×
196

197
        return outerClassName.equals(internalClassName);
×
198
    }
199

200
    @Override
201
    public FieldVisitor visitField(int access, @NonNull String name, @NonNull String desc, @Nullable String signature,
202
            @Nullable Object value) {
203
        if (fileData != null && simpleClassName != null && (access & FIELD_MODIFIERS_TO_IGNORE) == 0) {
×
204
            fileData.dataCoverageInfo.addField(simpleClassName, name, (access & STATIC) != 0);
×
205
        }
206

207
        return cw.visitField(access, name, desc, signature, value);
×
208
    }
209

210
    @Override
211
    public MethodVisitor visitMethod(int access, @NonNull String name, @NonNull String desc, @Nullable String signature,
212
            @Nullable String[] exceptions) {
213
        MethodWriter mw = cw.visitMethod(access, name, desc, signature, exceptions);
×
214

215
        if ((access & SYNTHETIC) != 0 || fileData == null || "<clinit>".equals(name) && forEnumClass) {
×
216
            return mw;
×
217
        }
218

219
        return new MethodModifier(mw, sourceFileName, fileData);
×
220
    }
221
}
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