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

wurstscript / WurstScript / 271

29 Sep 2025 12:12PM UTC coverage: 64.649% (+2.4%) from 62.222%
271

Pull #1096

circleci

Frotty
Merge branch 'perf-improvements' of https://github.com/wurstscript/WurstScript into perf-improvements
Pull Request #1096: Perf improvements

18202 of 28155 relevant lines covered (64.65%)

0.65 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.List;
15

16
import static de.peeeq.wurstscript.attributes.GenericsHelper.givenBinding;
17
import static de.peeeq.wurstscript.attributes.GenericsHelper.typeParameters;
18

19
public class AttrPossibleFunctionSignatures {
×
20

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

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

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

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

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

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

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

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

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

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

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

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

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

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

120

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

127
        ClassDef classDef = (ClassDef) typeDef;
1✔
128

129
        List<ConstructorDef> constructors = classDef.getConstructors();
1✔
130

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

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