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

wurstscript / WurstScript / 228

29 Nov 2023 05:00PM UTC coverage: 62.48% (-0.09%) from 62.574%
228

push

circleci

web-flow
Show dialog for choosing game path, cleanup (#1083)

* show dialog for choosing game path

* cleanup code

* remove logs and refactor

* remove confusing mpq error, make some mpq loads readonly

17295 of 27681 relevant lines covered (62.48%)

0.62 hits per line

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

84.38
de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/attributes/InitOrder.java
1
package de.peeeq.wurstscript.attributes;
2

3
import com.google.common.collect.ImmutableCollection;
4
import com.google.common.collect.ImmutableList;
5
import com.google.common.collect.Lists;
6
import com.google.common.collect.Sets;
7
import de.peeeq.wurstscript.ast.WImport;
8
import de.peeeq.wurstscript.ast.WImports;
9
import de.peeeq.wurstscript.ast.WPackage;
10

11
import java.util.*;
12

13
public class InitOrder {
×
14

15
    public static ImmutableList<WPackage> initDependencies(WPackage p) {
16
        Set<WPackage> packages = Sets.newLinkedHashSet();
1✔
17

18
        // add all imported packages, which do not import this package again
19
        packages.addAll(p.attrImportedPackagesTransitive());
1✔
20

21
        // add config package if it exists:
22
        WPackage configPackage = p.getModel().attrConfigOverridePackages().get(p);
1✔
23
        if (configPackage != null) {
1✔
24
            packages.add(configPackage);
1✔
25
        }
26

27
        return ImmutableList.copyOf(packages);
1✔
28
    }
29

30
    public static ImmutableList<WPackage> initDependenciesTransitive(WPackage p) {
31
        List<WPackage> result = Lists.newArrayList();
×
32
        for (WPackage dep : p.attrInitDependencies()) {
×
33
            addInitDependenciesTransitive(dep, result);
×
34
        }
×
35
        return ImmutableList.copyOf(result);
×
36
    }
37

38
    private static void addInitDependenciesTransitive(WPackage p, List<WPackage> result) {
39
        if (result.contains(p)) {
×
40
            return;
×
41
        }
42
        result.add(p);
×
43
        for (WPackage dep : p.attrInitDependencies()) {
×
44
            addInitDependenciesTransitive(dep, result);
×
45
        }
×
46
    }
×
47

48
    public static ImmutableCollection<WPackage> importedPackagesTrans(WPackage p) {
49
        Collection<WPackage> result = Sets.newLinkedHashSet();
1✔
50
        Set<String> reportedErrors = Sets.newHashSet();
1✔
51
        List<WPackage> callStack = Lists.newArrayList();
1✔
52
        // the old cyclic check reports cyclic dependencies as errors
53
        // it ignores cyclic dependencies caused by config packages
54
        // it stores reported errors in reportedErrors
55
        collectImportedPackages(callStack, p, result, reportedErrors, false, false);
1✔
56
        // the new cyclic check reports cyclic dependencies caused by config packages as warnings
57
        // it does not report warnings for cyclic dependencies stored in reportedErrors
58
        collectImportedPackages(callStack, p, Sets.newLinkedHashSet(), reportedErrors, true, true);
1✔
59
        // only the result of the old cyclic check is used
60
        return ImmutableList.copyOf(result);
1✔
61
    }
62

63
    private static String getCyclicDependencyString(List<WPackage> callStack, WPackage imported) {
64
        return getCyclicDependencyString(callStack, imported, false);
1✔
65
    }
66

67
    private static String getCyclicDependencyString(List<WPackage> callStack, WPackage imported, boolean considerConfig) {
68
        // string representation of a cyclic dependency
69
        // used for the error message and for storing already reported cyclic dependencies
70
        StringBuilder msg = new StringBuilder();
1✔
71
        Map<WPackage, WPackage> configuredPackage = new HashMap<>();
1✔
72
        if (considerConfig) {
1✔
73
            for (WPackage configured : imported.getModel().attrConfigOverridePackages().keySet()) {
1✔
74
                configuredPackage.put(imported.getModel().attrConfigOverridePackages().get(configured), configured);
1✔
75
            }
1✔
76
        }
77
        for (WPackage p : callStack) {
1✔
78
            String packageString = p.getName();
1✔
79
            if (considerConfig && configuredPackage.containsKey(p)) {
1✔
80
                packageString = configuredPackage.get(p).getName() + "/" + packageString;
1✔
81
            }
82
            msg.append(packageString).append(" -> ");
1✔
83
        }
1✔
84
        String importedString = imported.getName();
1✔
85
        if (considerConfig && configuredPackage.containsKey(imported)) {
1✔
86
            importedString = configuredPackage.get(imported).getName() + "/" + importedString;
1✔
87
        }
88
        return msg + importedString;
1✔
89
    }
90

91
    private static String getErrorMsg(List<WPackage> callStack, WPackage imported) {
92
        String cyclicDependency = getCyclicDependencyString(callStack, imported, false);
1✔
93
        return "Cyclic init dependency between packages: " + cyclicDependency +
1✔
94
            "\nChange some imports to 'initlater' imports to avoid this problem.";
95
    }
96

97
    private static String getWarningMsg(List<WPackage> callStack, WPackage imported) {
98
        String cyclicDependency = getCyclicDependencyString(callStack, imported, true);
1✔
99
        return "Cyclic init dependency between packages: " + cyclicDependency +
1✔
100
            "\nChange some imports to 'initlater' imports to avoid this problem." +
101
            "\nThis will be an error in future Wurst versions.";
102
    }
103

104
    private static void reportCyclicDependency(List<WPackage> callStack, WPackage wPackage, Set<String> reportedErrors, boolean useWarnings) {
105
        String cyclicString = getCyclicDependencyString(callStack, wPackage);
1✔
106
        String errorMsg = getErrorMsg(callStack, wPackage);
1✔
107
        String warningMsg = getWarningMsg(callStack, wPackage);
1✔
108
        for (WImport imp : wPackage.getImports()) {
1✔
109
            if (callStack.size() > 1 && imp.attrImportedPackage() == callStack.get(1)) {
1✔
110
                if (!reportedErrors.contains(cyclicString)) {
1✔
111
                    reportedErrors.add(cyclicString);
1✔
112
                    if (useWarnings) {
1✔
113
                        wPackage.addWarning(warningMsg);
1✔
114
                    } else {
115
                        wPackage.addError(errorMsg);
×
116
                    }
117
                }
118
                return;
1✔
119
            }
120
        }
1✔
121
        if (!reportedErrors.contains(cyclicString)) {
1✔
122
            reportedErrors.add(cyclicString);
1✔
123
            if (useWarnings) {
1✔
124
                wPackage.addWarning(warningMsg);
1✔
125
            } else {
126
                wPackage.addError(errorMsg);
×
127
            }
128
        }
129
    }
1✔
130

131
    private static void addCollectImportedPackage(List<WPackage> callStack, WPackage p, Collection<WPackage> result, WImports imports, Set<String> reportedErrors, boolean considerConfig, boolean useWarnings) {
132
        for (WImport i : imports) {
1✔
133
            WPackage imported = i.attrImportedPackage();
1✔
134

135
            if (imported == null || i.getIsInitLater()) {
1✔
136
                continue;
1✔
137
            }
138
            if (imported == p) {
1✔
139
                // import self is handled elsewhere
140
                continue;
1✔
141
            }
142

143
            if (imported == callStack.get(0)) {
1✔
144
                reportCyclicDependency(callStack, imported, reportedErrors, useWarnings);
1✔
145
                return;
1✔
146
            }
147

148
            if (!result.contains(imported)) {
1✔
149
                result.add(imported);
1✔
150
                collectImportedPackages(callStack, imported, result, reportedErrors, considerConfig, useWarnings);
1✔
151
            }
152
            // add imports of configured package to config package
153
            // that way cyclic dependencies are checked for the config package and errors will be reported for the config package
154
            if (considerConfig) {
1✔
155
                WPackage configPackage = p.getModel().attrConfigOverridePackages().get(imported);
1✔
156
                if (configPackage != null && configPackage != p) {
1✔
157
                    if (configPackage == callStack.get(0)) {
1✔
158
                        reportCyclicDependency(callStack, configPackage, reportedErrors, useWarnings);
1✔
159
                        return;
1✔
160
                    }
161
                    if (!result.contains(configPackage)) {
1✔
162
                        result.add(configPackage);
1✔
163
                        collectImportedPackages(callStack, configPackage, result, reportedErrors, considerConfig, useWarnings);
1✔
164
                    }
165
                }
166
            }
167
        }
1✔
168
    }
1✔
169

170
    private static void collectImportedPackages(List<WPackage> callStack, WPackage p, Collection<WPackage> result, Set<String> reportedErrors, boolean considerConfig, boolean useWarnings) {
171
        callStack.add(p);
1✔
172
        addCollectImportedPackage(callStack, p, result, p.getImports(), reportedErrors, considerConfig, useWarnings);
1✔
173
        /*
174
        Imports of config packages are added to the imports of the configured package.
175
        Since config packages are initialized directly before the configured package,
176
        all imports are merged on the configured package to ensure it is initialized at the correct time.
177
        This enables importing the configured package in the config package,
178
        even though the configured package will be initialized after the config package.
179
         */
180
        if (considerConfig) {
1✔
181
            for (Map.Entry<WPackage, WPackage> e : p.getModel().attrConfigOverridePackages().entrySet()) {
1✔
182
                if (e.getValue().equals(p)) {
1✔
183
                    addCollectImportedPackage(callStack, e.getKey(), result, e.getKey().getImports(), reportedErrors, considerConfig, useWarnings);
1✔
184
                }
185
            }
1✔
186
        }
187
        callStack.remove(callStack.size() - 1);
1✔
188
    }
1✔
189

190
}
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

© 2025 Coveralls, Inc