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

wurstscript / WurstScript / 265

29 Sep 2025 09:00AM UTC coverage: 62.244% (+0.02%) from 62.222%
265

Pull #1096

circleci

Frotty
restore determinism, fix tests
Pull Request #1096: Perf improvements

17480 of 28083 relevant lines covered (62.24%)

0.62 hits per line

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

94.59
de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/attributes/AttrPossibleFunctionSignatures.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 de.peeeq.wurstscript.ast.*;
7
import de.peeeq.wurstscript.attributes.names.FuncLink;
8
import de.peeeq.wurstscript.types.FunctionSignature;
9
import de.peeeq.wurstscript.types.FunctionSignature.ArgsMatchResult;
10
import de.peeeq.wurstscript.types.VariableBinding;
11
import de.peeeq.wurstscript.types.VariablePosition;
12
import de.peeeq.wurstscript.types.WurstType;
13

14
import java.util.Collections;
15
import java.util.Comparator;
16
import java.util.List;
17

18
import static de.peeeq.wurstscript.attributes.GenericsHelper.givenBinding;
19
import static de.peeeq.wurstscript.attributes.GenericsHelper.typeParameters;
20

21
public class AttrPossibleFunctionSignatures {
×
22

23
    public static ImmutableCollection<FunctionSignature> calculate(FunctionCall fc) {
24
        ImmutableCollection<FuncLink> fs = fc.attrPossibleFuncDefs();
1✔
25
        ImmutableCollection.Builder<FunctionSignature> resultBuilder = ImmutableList.builder();
1✔
26
        for (FuncLink f : fs) {
1✔
27
            FunctionSignature sig = FunctionSignature.fromNameLink(f);
1✔
28

29
            OptExpr implicitParameterOpt = AttrImplicitParameter.getFunctionCallImplicitParameter(fc, f, false);
1✔
30
            if (implicitParameterOpt instanceof Expr) {
1✔
31
                Expr expr = (Expr) implicitParameterOpt;
1✔
32
                VariableBinding mapping = expr.attrTyp().matchAgainstSupertype(sig.getReceiverType(), fc, sig.getMapping(), VariablePosition.RIGHT);
1✔
33
                if (mapping == null) {
1✔
34
                    // TODO error message? Or just ignore wrong parameter type?
35
                    continue;
×
36
                } else {
37
                    sig = sig.setTypeArgs(fc, mapping);
1✔
38
                }
39
            } // TODO else check?
40

41
            VariableBinding mapping = givenBinding(fc, sig.getDefinitionTypeVariables());
1✔
42
            sig = sig.setTypeArgs(fc, mapping);
1✔
43

44
            resultBuilder.add(sig);
1✔
45
        }
1✔
46
        return findBestSignature(fc, resultBuilder.build());
1✔
47
    }
48

49
    private static ImmutableCollection<FunctionSignature> findBestSignature(StmtCall fc,
50
                                                                            ImmutableCollection<FunctionSignature> res) {
51
        // Fast path: nothing to consider
52
        if (res.isEmpty()) {
1✔
53
            return ImmutableList.of();
1✔
54
        }
55

56
        // Materialize once to a random-access list (cheap for Immutable*)
57
        final ImmutableList<FunctionSignature> sigs =
58
            (res instanceof ImmutableList)
1✔
59
                ? (ImmutableList<FunctionSignature>) res
1✔
60
                : ImmutableList.copyOf(res);
1✔
61

62
        // Compute arg types once
63
        final List<WurstType> argTypes = AttrFuncDef.argumentTypesPre(fc);
1✔
64

65
        // --- Pass 1: exact matches only (cheap) ---------------------------------
66
        // Use a single ArrayList and only copy if we actually have matches.
67
        List<FunctionSignature> exact = new java.util.ArrayList<>(sigs.size());
1✔
68
        for (int i = 0, n = sigs.size(); i < n; i++) {
1✔
69
            FunctionSignature matched = sigs.get(i).matchAgainstArgs(argTypes, fc);
1✔
70
            if (matched != null) {
1✔
71
                exact.add(matched);
1✔
72
            }
73
        }
74
        if (!exact.isEmpty()) {
1✔
75
            return ImmutableList.copyOf(exact);
1✔
76
        }
77

78
        // --- Pass 2: best-effort matches (no exact match) ------------------------
79
        // We must:
80
        //  * find the min-badness result (to emit its errors)
81
        //  * return ALL resulting signatures (to preserve current semantics)
82
        final int n = sigs.size();
1✔
83
        FunctionSignature[] inferredSigs = new FunctionSignature[n];
1✔
84
        int bestIdx = -1;
1✔
85
        int bestBadness = Integer.MAX_VALUE;
1✔
86
        ArgsMatchResult bestResult = null;
1✔
87

88
        // Cache args node once
89
        final Arguments argsNode = fc.getArgs();
1✔
90

91
        for (int i = 0; i < n; i++) {
1✔
92
            // tryMatchAgainstArgs may also perform type-arg inference; we must keep its result sig
93
            ArgsMatchResult r = sigs.get(i).tryMatchAgainstArgs(argTypes, argsNode, fc);
1✔
94
            inferredSigs[i] = r.getSig();
1✔
95
            int b = r.getBadness();
1✔
96
            if (b < bestBadness) {
1✔
97
                bestBadness = b;
1✔
98
                bestIdx = i;
1✔
99
                bestResult = r;
1✔
100
            }
101
        }
102

103
        if (bestIdx == -1 || bestResult == null) {
1✔
104
            // Shouldn’t happen, but be safe
105
            return ImmutableList.of();
×
106
        }
107

108
        // Emit errors from the best match (same as before)
109
        for (CompileError c : bestResult.getErrors()) {
1✔
110
            fc.getErrorHandler().sendError(c);
1✔
111
        }
1✔
112

113
        // Return ALL candidate signatures (same as previous behavior)
114
        // Avoid another stream/collect
115
        ImmutableList.Builder<FunctionSignature> out = ImmutableList.builderWithExpectedSize(n);
1✔
116
        for (int i = 0; i < n; i++) {
1✔
117
            out.add(inferredSigs[i]);
1✔
118
        }
119
        return out.build();
1✔
120
    }
121

122

123
    public static ImmutableCollection<FunctionSignature> calculate(ExprNewObject fc) {
124
        TypeDef typeDef = fc.attrTypeDef();
1✔
125
        if (!(typeDef instanceof ClassDef)) {
1✔
126
            return ImmutableList.of();
×
127
        }
128

129
        ClassDef classDef = (ClassDef) typeDef;
1✔
130

131
        List<ConstructorDef> constructors = classDef.getConstructors();
1✔
132

133
        ImmutableList.Builder<FunctionSignature> res = ImmutableList.builder();
1✔
134
        for (ConstructorDef f : constructors) {
1✔
135
            WurstType returnType = classDef.attrTyp().dynamic();
1✔
136
            VariableBinding binding2 = givenBinding(fc, typeParameters(classDef));
1✔
137
            List<WurstType> paramTypes = Lists.newArrayList();
1✔
138
            for (WParameter p : f.getParameters()) {
1✔
139
                paramTypes.add(p.attrTyp());
1✔
140
            }
1✔
141
            List<String> pNames = FunctionSignature.getParamNames(f.getParameters());
1✔
142
            List<TypeParamDef> typeParams = classDef.getTypeParameters();
1✔
143
            VariableBinding mapping = VariableBinding.emptyMapping().withTypeVariables(typeParams);
1✔
144
            FunctionSignature sig = new FunctionSignature(f, mapping, null, "construct", paramTypes, pNames, returnType);
1✔
145
            sig = sig.setTypeArgs(fc, binding2);
1✔
146
            res.add(sig);
1✔
147
        }
1✔
148
        return findBestSignature(fc, res.build());
1✔
149
    }
150

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