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

mybatis / generator / 2010

03 Feb 2026 08:32PM UTC coverage: 89.961% (+0.2%) from 89.808%
2010

push

github

web-flow
Merge pull request #1437 from jeffgbutler/refactor-javamerger

Java Merger Enhancements - Support Records and Enums

2294 of 3071 branches covered (74.7%)

161 of 170 new or added lines in 5 files covered. (94.71%)

1 existing line in 1 file now uncovered.

11631 of 12929 relevant lines covered (89.96%)

0.9 hits per line

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

92.45
/core/mybatis-generator-core/src/main/java/org/mybatis/generator/merge/java/JavaMergeUtilities.java
1
/*
2
 *    Copyright 2006-2026 the original author or authors.
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
 *       https://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 org.mybatis.generator.merge.java;
17

18
import java.util.ArrayList;
19
import java.util.Collections;
20
import java.util.List;
21
import java.util.stream.Collectors;
22

23
import com.github.javaparser.ast.CompilationUnit;
24
import com.github.javaparser.ast.ImportDeclaration;
25
import com.github.javaparser.ast.body.BodyDeclaration;
26
import com.github.javaparser.ast.body.FieldDeclaration;
27
import com.github.javaparser.ast.body.VariableDeclarator;
28
import com.github.javaparser.ast.nodeTypes.NodeWithSimpleName;
29
import com.github.javaparser.ast.type.ClassOrInterfaceType;
30

31
public class JavaMergeUtilities {
32
    private JavaMergeUtilities() {
33
        // utility class, no instances
34
    }
35

36
    /**
37
     * Compare two compilation units and find imports that are in the existing file but not in the new file.
38
     * We assume this means they are required for some custom method, so we will add them to the new
39
     * file if there are other items to merge. This may create unused imports in the new file if the
40
     * initial assumption is incorrect, but better safe than sorry.
41
     *
42
     * @param existingCompilationUnit compilation unit representing the existing file
43
     * @param newCompilationUnit compilation unit representing the new file
44
     */
45
    public static List<ImportDeclaration> findCustomImports(CompilationUnit existingCompilationUnit,
46
                                                            CompilationUnit newCompilationUnit) {
47
        List<ImportDeclaration> customImports = new ArrayList<>();
1✔
48

49
        List<String> newFileImports = newCompilationUnit.getImports().stream()
1✔
50
                .map(JavaMergeUtilities::stringify).toList();
1✔
51

52
        for (ImportDeclaration id : existingCompilationUnit.getImports()) {
1✔
53
            if (!newFileImports.contains(stringify(id))) {
1✔
54
                customImports.add(id);
1✔
55
            }
56
        }
1✔
57

58
        return customImports;
1✔
59
    }
60

61
    /**
62
     * Compare two members to see if they are "functionally equivalent". This is defined as:
63
     *
64
     * <ul>
65
     *     <li>Members are the same type</li>
66
     *     <li>Members have the same signature or basic declaration</li>
67
     * </ul>
68
     *
69
     * @param member1 the first member
70
     * @param member2 the second member
71
     * @return true if the members are functionally equivalent
72
     */
73
    public static boolean membersMatch(BodyDeclaration<?> member1, BodyDeclaration<?> member2) {
74
        if (member1.isTypeDeclaration() && member2.isTypeDeclaration()) {
1✔
75
            return member1.asTypeDeclaration().getNameAsString()
1✔
76
                    .equals(member2.asTypeDeclaration().getNameAsString());
1✔
77
        } else if (member1.isCallableDeclaration() && member2.isCallableDeclaration()) {
1✔
78
            return member1.asCallableDeclaration().getSignature().asString()
1✔
79
                    .equals(member2.asCallableDeclaration().getSignature().asString());
1✔
80
        } else if (member1.isFieldDeclaration() && member2.isFieldDeclaration()) {
1!
81
            return stringify(member1.asFieldDeclaration()).equals(stringify(member2.asFieldDeclaration()));
1✔
82
        }
83

84
        return false;
1✔
85
    }
86

87
    public static List<ClassOrInterfaceType> findCustomSuperInterfaces(BodyDeclaration<?> existingType,
88
                                                                       BodyDeclaration<?> newType) {
89
        List<ClassOrInterfaceType> customSuperInterfaces = new ArrayList<>();
1✔
90

91
        List<String> newFileSuperInterfaces = findSuperInterfaces(newType).stream()
1✔
92
                .map(NodeWithSimpleName::getNameAsString).toList();
1✔
93

94
        for (ClassOrInterfaceType id : findSuperInterfaces(existingType)) {
1✔
95
            if (!newFileSuperInterfaces.contains(id.getNameAsString())) {
1✔
96
                customSuperInterfaces.add(id);
1✔
97
            }
98
        }
1✔
99

100
        return customSuperInterfaces;
1✔
101
    }
102

103
    public static List<ClassOrInterfaceType> findSuperInterfaces(BodyDeclaration<?> bodyDeclaration) {
104
        if (bodyDeclaration.isClassOrInterfaceDeclaration()) {
1✔
105
            return bodyDeclaration.asClassOrInterfaceDeclaration().getImplementedTypes();
1✔
106
        } else if (bodyDeclaration.isEnumDeclaration()) {
1✔
107
            return bodyDeclaration.asEnumDeclaration().getImplementedTypes();
1✔
108
        } else if (bodyDeclaration.isRecordDeclaration()) {
1!
109
            return bodyDeclaration.asRecordDeclaration().getImplementedTypes();
1✔
110
        }
111

NEW
112
        return Collections.emptyList();
×
113
    }
114

115
    public static void addSuperInterface(BodyDeclaration<?> bodyDeclaration, ClassOrInterfaceType superInterface) {
116
        if (bodyDeclaration.isClassOrInterfaceDeclaration()) {
1✔
117
            bodyDeclaration.asClassOrInterfaceDeclaration().addImplementedType(superInterface);
1✔
118
        } else if (bodyDeclaration.isEnumDeclaration()) {
1!
NEW
119
            bodyDeclaration.asEnumDeclaration().addImplementedType(superInterface);
×
120
        } else if (bodyDeclaration.isRecordDeclaration()) {
1!
121
            bodyDeclaration.asRecordDeclaration().addImplementedType(superInterface);
1✔
122
        }
123
    }
1✔
124

125
    /**
126
     * Create a string representation of an import that we can use to find matches.
127
     *
128
     * @param importDeclaration the import declaration to stringify
129
     * @return string representation of the import (not a full import statement)
130
     */
131
    public static String stringify(ImportDeclaration importDeclaration) {
132
        StringBuilder sb = new StringBuilder();
1✔
133
        if (importDeclaration.isStatic()) {
1✔
134
            sb.append("static "); //$NON-NLS-1$
1✔
135
        }
136
        if (importDeclaration.isModule()) {
1!
NEW
137
            sb.append("module "); //$NON-NLS-1$
×
138
        }
139
        sb.append(importDeclaration.getNameAsString());
1✔
140
        if (importDeclaration.isAsterisk()) {
1!
NEW
141
            sb.append(".*"); //$NON-NLS-1$
×
142
        }
143

144
        return sb.toString();
1✔
145
    }
146

147
    public static String stringify(FieldDeclaration fieldDeclaration) {
148
        return fieldDeclaration.getVariables().stream()
1✔
149
                .map(JavaMergeUtilities::stringify)
1✔
150
                .collect(Collectors.joining(",")); //$NON-NLS-1$
1✔
151
    }
152

153
    public static String stringify(VariableDeclarator variableDeclarator) {
154
        return variableDeclarator.getType().toString()
1✔
155
                + " " //$NON-NLS-1$
156
                + variableDeclarator.getName().toString();
1✔
157
    }
158
}
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