Example usage for com.google.common.collect ImmutableList indexOf

List of usage examples for com.google.common.collect ImmutableList indexOf

Introduction

In this page you can find the example usage for com.google.common.collect ImmutableList indexOf.

Prototype

@Override
    public int indexOf(@Nullable Object object) 

Source Link

Usage

From source file:org.locationtech.geogig.plumbing.diff.FeatureDiff.java

/**
 * /*from  w w w  .ja va 2  s .c om*/
 * @param path the full path to the feature, including its name
 * @param newRevFeature the new version of the feature
 * @param oldRevFeature the old version of the feature
 * @param newRevFeatureType the new version of the feature type
 * @param oldRevFeatureType the old version of the feature type
 * @param all - true if all attributes should be added regardless of change
 */
public FeatureDiff(String path, @Nullable RevFeature newRevFeature, @Nullable RevFeature oldRevFeature,
        @Nullable RevFeatureType newRevFeatureType, @Nullable RevFeatureType oldRevFeatureType, boolean all) {

    this.path = path;
    this.newRevFeature = newRevFeature;
    this.oldRevFeature = oldRevFeature;
    this.newFeatureType = newRevFeatureType;
    this.oldFeatureType = oldRevFeatureType;
    diffs = new HashMap<PropertyDescriptor, AttributeDiff>();

    if (newRevFeature == null) {
        Preconditions.checkArgument(oldRevFeature != null, "A feature must be provided");
        Preconditions.checkArgument(oldRevFeatureType != null, "Old feature type must be provided.");

        ImmutableList<PropertyDescriptor> oldAttributes = oldRevFeatureType.descriptors();

        for (int i = 0; i < oldAttributes.size(); i++) {
            Optional<Object> oldValue = oldRevFeature.get(i);
            PropertyDescriptor descriptor = oldAttributes.get(i);
            if (Geometry.class.isAssignableFrom(descriptor.getType().getBinding())) {
                diffs.put(descriptor, new GeometryAttributeDiff((Geometry) oldValue.orNull(), (Geometry) null));
            } else {
                diffs.put(oldAttributes.get(i), new GenericAttributeDiffImpl(oldValue.orNull(), null));
            }
        }
    } else if (oldRevFeature == null) {
        Preconditions.checkArgument(newRevFeatureType != null, "New feature type must be provided.");

        ImmutableList<PropertyDescriptor> newAttributes = newRevFeatureType.descriptors();

        for (int i = 0; i < newAttributes.size(); i++) {
            Optional<Object> newValue = newRevFeature.get(i);
            PropertyDescriptor descriptor = newAttributes.get(i);
            if (Geometry.class.isAssignableFrom(descriptor.getType().getBinding())) {
                diffs.put(descriptor, new GeometryAttributeDiff((Geometry) null, (Geometry) newValue.orNull()));
            } else {
                diffs.put(newAttributes.get(i), new GenericAttributeDiffImpl(null, newValue.orNull()));
            }
        }
    } else {
        ImmutableList<PropertyDescriptor> oldAttributes = oldRevFeatureType.descriptors();
        ImmutableList<PropertyDescriptor> newAttributes = newRevFeatureType.descriptors();
        BitSet updatedAttributes = new BitSet(newRevFeature.size());
        for (int i = 0; i < oldAttributes.size(); i++) {
            Optional<Object> oldValue = oldRevFeature.get(i);
            int idx = newAttributes.indexOf(oldAttributes.get(i));
            if (idx != -1) {
                Optional<Object> newValue = newRevFeature.get(idx);
                if (!oldValue.equals(newValue) || all) {
                    if (Geometry.class.isAssignableFrom(oldAttributes.get(i).getType().getBinding())) {
                        diffs.put(oldAttributes.get(i), new GeometryAttributeDiff((Geometry) oldValue.orNull(),
                                (Geometry) newValue.orNull()));
                    } else {
                        diffs.put(oldAttributes.get(i),
                                new GenericAttributeDiffImpl(oldValue.orNull(), newValue.orNull()));
                    }
                }
                updatedAttributes.set(idx);
            } else {
                if (Geometry.class.isAssignableFrom(oldAttributes.get(i).getType().getBinding())) {
                    diffs.put(oldAttributes.get(i),
                            new GeometryAttributeDiff((Geometry) oldValue.orNull(), (Geometry) null));
                } else {
                    diffs.put(oldAttributes.get(i), new GenericAttributeDiffImpl(oldValue.orNull(), null));
                }
            }
        }
        updatedAttributes.flip(0, newRevFeature.size());
        for (int i = updatedAttributes.nextSetBit(0); i >= 0; i = updatedAttributes.nextSetBit(i + 1)) {
            PropertyDescriptor descriptor = newAttributes.get(i);
            if (Geometry.class.isAssignableFrom(descriptor.getType().getBinding())) {
                diffs.put(descriptor,
                        new GeometryAttributeDiff((Geometry) null, (Geometry) newRevFeature.get(i).orNull()));
            } else {
                diffs.put(descriptor, new GenericAttributeDiffImpl(null, newRevFeature.get(i).orNull()));
            }
        }
    }

}

From source file:cpw.mods.fml.common.FMLModContainer.java

@Subscribe
public void constructMod(FMLConstructionEvent event) {
    try {//from w  w  w  . java 2 s.  com
        ModClassLoader modClassLoader = event.getModClassLoader();
        modClassLoader.addFile(source);
        modClassLoader.clearNegativeCacheFor(candidate.getClassList());
        Class<?> clazz = Class.forName(className, true, modClassLoader);

        Certificate[] certificates = clazz.getProtectionDomain().getCodeSource().getCertificates();
        int len = 0;
        if (certificates != null) {
            len = certificates.length;
        }
        Builder<String> certBuilder = ImmutableList.<String>builder();
        for (int i = 0; i < len; i++) {
            certBuilder.add(CertificateHelper.getFingerprint(certificates[i]));
        }

        ImmutableList<String> certList = certBuilder.build();
        sourceFingerprints = ImmutableSet.copyOf(certList);

        String expectedFingerprint = (String) descriptor.get("certificateFingerprint");

        fingerprintNotPresent = true;

        if (expectedFingerprint != null && !expectedFingerprint.isEmpty()) {
            if (!sourceFingerprints.contains(expectedFingerprint)) {
                Level warnLevel = Level.ERROR;
                if (source.isDirectory()) {
                    warnLevel = Level.TRACE;
                }
                FMLLog.log(getModId(), warnLevel,
                        "The mod %s is expecting signature %s for source %s, however there is no signature matching that description",
                        getModId(), expectedFingerprint, source.getName());
            } else {
                certificate = certificates[certList.indexOf(expectedFingerprint)];
                fingerprintNotPresent = false;
            }
        }

        @SuppressWarnings("unchecked")
        List<Map<String, Object>> props = (List<Map<String, Object>>) descriptor.get("customProperties");
        if (props != null) {
            com.google.common.collect.ImmutableMap.Builder<String, String> builder = ImmutableMap
                    .<String, String>builder();
            for (Map<String, Object> p : props) {
                builder.put((String) p.get("k"), (String) p.get("v"));
            }
            customModProperties = builder.build();
        } else {
            customModProperties = EMPTY_PROPERTIES;
        }

        Boolean hasDisableableFlag = (Boolean) descriptor.get("canBeDeactivated");
        boolean hasReverseDepends = !event.getReverseDependencies().get(getModId()).isEmpty();
        if (hasDisableableFlag != null && hasDisableableFlag) {
            disableability = hasReverseDepends ? Disableable.DEPENDENCIES : Disableable.YES;
        } else {
            disableability = hasReverseDepends ? Disableable.DEPENDENCIES : Disableable.RESTART;
        }
        Method factoryMethod = gatherAnnotations(clazz);
        modInstance = getLanguageAdapter().getNewInstance(this, clazz, modClassLoader, factoryMethod);
        NetworkRegistry.INSTANCE.register(this, clazz,
                (String) (descriptor.containsKey("acceptableRemoteVersions")
                        ? descriptor.get("acceptableRemoteVersions")
                        : null),
                event.getASMHarvestedData());
        if (fingerprintNotPresent) {
            eventBus.post(new FMLFingerprintViolationEvent(source.isDirectory(), source,
                    ImmutableSet.copyOf(this.sourceFingerprints), expectedFingerprint));
        }
        ProxyInjector.inject(this, event.getASMHarvestedData(), FMLCommonHandler.instance().getSide(),
                getLanguageAdapter());
        processFieldAnnotations(event.getASMHarvestedData());
    } catch (Throwable e) {
        controller.errorOccurred(this, e);
        Throwables.propagateIfPossible(e);
    }
}

From source file:net.minecraftforge.fml.common.FMLModContainer.java

@Subscribe
public void constructMod(FMLConstructionEvent event) {
    try {//w ww .j  a v a2 s  . c om
        BlamingTransformer.addClasses(getModId(), candidate.getClassList());
        ModClassLoader modClassLoader = event.getModClassLoader();
        modClassLoader.addFile(source);
        modClassLoader.clearNegativeCacheFor(candidate.getClassList());
        Class<?> clazz = Class.forName(className, true, modClassLoader);

        Certificate[] certificates = clazz.getProtectionDomain().getCodeSource().getCertificates();
        int len = 0;
        if (certificates != null) {
            len = certificates.length;
        }
        Builder<String> certBuilder = ImmutableList.<String>builder();
        for (int i = 0; i < len; i++) {
            certBuilder.add(CertificateHelper.getFingerprint(certificates[i]));
        }

        ImmutableList<String> certList = certBuilder.build();
        sourceFingerprints = ImmutableSet.copyOf(certList);

        String expectedFingerprint = (String) descriptor.get("certificateFingerprint");

        fingerprintNotPresent = true;

        if (expectedFingerprint != null && !expectedFingerprint.isEmpty()) {
            if (!sourceFingerprints.contains(expectedFingerprint)) {
                Level warnLevel = Level.ERROR;
                if (source.isDirectory()) {
                    warnLevel = Level.TRACE;
                }
                FMLLog.log(getModId(), warnLevel,
                        "The mod %s is expecting signature %s for source %s, however there is no signature matching that description",
                        getModId(), expectedFingerprint, source.getName());
            } else {
                certificate = certificates[certList.indexOf(expectedFingerprint)];
                fingerprintNotPresent = false;
            }
        }

        @SuppressWarnings("unchecked")
        List<Map<String, Object>> props = (List<Map<String, Object>>) descriptor.get("customProperties");
        if (props != null) {
            com.google.common.collect.ImmutableMap.Builder<String, String> builder = ImmutableMap
                    .<String, String>builder();
            for (Map<String, Object> p : props) {
                builder.put((String) p.get("k"), (String) p.get("v"));
            }
            customModProperties = builder.build();
        } else {
            customModProperties = EMPTY_PROPERTIES;
        }

        Boolean hasDisableableFlag = (Boolean) descriptor.get("canBeDeactivated");
        boolean hasReverseDepends = !event.getReverseDependencies().get(getModId()).isEmpty();
        if (hasDisableableFlag != null && hasDisableableFlag) {
            disableability = hasReverseDepends ? Disableable.DEPENDENCIES : Disableable.YES;
        } else {
            disableability = hasReverseDepends ? Disableable.DEPENDENCIES : Disableable.RESTART;
        }
        Method factoryMethod = gatherAnnotations(clazz);
        modInstance = getLanguageAdapter().getNewInstance(this, clazz, modClassLoader, factoryMethod);
        NetworkRegistry.INSTANCE.register(this, clazz,
                (String) (descriptor.containsKey("acceptableRemoteVersions")
                        ? descriptor.get("acceptableRemoteVersions")
                        : null),
                event.getASMHarvestedData());
        if (fingerprintNotPresent) {
            eventBus.post(new FMLFingerprintViolationEvent(source.isDirectory(), source,
                    ImmutableSet.copyOf(this.sourceFingerprints), expectedFingerprint));
        }
        ProxyInjector.inject(this, event.getASMHarvestedData(), FMLCommonHandler.instance().getSide(),
                getLanguageAdapter());
        processFieldAnnotations(event.getASMHarvestedData());
    } catch (Throwable e) {
        controller.errorOccurred(this, e);
    }
}

From source file:org.apache.calcite.rel.metadata.ReflectiveRelMetadataProvider.java

private static RelMetadataProvider reflectiveSource(final MetadataHandler target,
        final ImmutableList<Method> methods) {
    final Space2 space = Space2.create(target, methods);

    // This needs to be a concurrent map since RelMetadataProvider are cached in static
    // fields, thus the map is subject to concurrent modifications later.
    // See map.put in org.apache.calcite.rel.metadata.ReflectiveRelMetadataProvider.apply(
    // java.lang.Class<? extends org.apache.calcite.rel.RelNode>)
    final ConcurrentMap<Class<RelNode>, UnboundMetadata> methodsMap = new ConcurrentHashMap<>();
    for (Class<RelNode> key : space.classes) {
        ImmutableNullableList.Builder<Method> builder = ImmutableNullableList.builder();
        for (final Method method : methods) {
            builder.add(space.find(key, method));
        }//from   w w w.  j av  a2  s  .  c o  m
        final List<Method> handlerMethods = builder.build();
        final UnboundMetadata function = new UnboundMetadata() {
            public Metadata bind(final RelNode rel, final RelMetadataQuery mq) {
                return (Metadata) Proxy.newProxyInstance(space.metadataClass0.getClassLoader(),
                        new Class[] { space.metadataClass0 }, new InvocationHandler() {
                            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                                // Suppose we are an implementation of Selectivity
                                // that wraps "filter", a LogicalFilter. Then we
                                // implement
                                //   Selectivity.selectivity(rex)
                                // by calling method
                                //   new SelectivityImpl().selectivity(filter, rex)
                                if (method.equals(BuiltInMethod.METADATA_REL.method)) {
                                    return rel;
                                }
                                if (method.equals(BuiltInMethod.OBJECT_TO_STRING.method)) {
                                    return space.metadataClass0.getSimpleName() + "(" + rel + ")";
                                }
                                int i = methods.indexOf(method);
                                if (i < 0) {
                                    throw new AssertionError("not handled: " + method + " for " + rel);
                                }
                                final Method handlerMethod = handlerMethods.get(i);
                                if (handlerMethod == null) {
                                    throw new AssertionError("not handled: " + method + " for " + rel);
                                }
                                final Object[] args1;
                                final List key;
                                if (args == null) {
                                    args1 = new Object[] { rel, mq };
                                    key = FlatLists.of(rel, method);
                                } else {
                                    args1 = new Object[args.length + 2];
                                    args1[0] = rel;
                                    args1[1] = mq;
                                    System.arraycopy(args, 0, args1, 2, args.length);

                                    final Object[] args2 = args1.clone();
                                    args2[1] = method; // replace RelMetadataQuery with method
                                    for (int j = 0; j < args2.length; j++) {
                                        if (args2[j] == null) {
                                            args2[j] = NullSentinel.INSTANCE;
                                        } else if (args2[j] instanceof RexNode) {
                                            // Can't use RexNode.equals - it is not deep
                                            args2[j] = args2[j].toString();
                                        }
                                    }
                                    key = FlatLists.copyOf(args2);
                                }
                                if (mq.map.put(key, NullSentinel.INSTANCE) != null) {
                                    throw CyclicMetadataException.INSTANCE;
                                }
                                try {
                                    return handlerMethod.invoke(target, args1);
                                } catch (InvocationTargetException | UndeclaredThrowableException e) {
                                    Util.throwIfUnchecked(e.getCause());
                                    throw new RuntimeException(e.getCause());
                                } finally {
                                    mq.map.remove(key);
                                }
                            }
                        });
            }
        };
        methodsMap.put(key, function);
    }
    return new ReflectiveRelMetadataProvider(methodsMap, space.metadataClass0, space.providerMap);
}

From source file:org.apache.calcite.rel.metadata.JaninoRelMetadataProvider.java

private static <M extends Metadata> MetadataHandler<M> load3(MetadataDef<M> def,
        Multimap<Method, MetadataHandler<M>> map, ImmutableList<Class<? extends RelNode>> relClasses) {
    final StringBuilder buff = new StringBuilder();
    final String name = "GeneratedMetadataHandler_" + def.metadataClass.getSimpleName();
    final Set<MetadataHandler> providerSet = new HashSet<>();
    final List<Pair<String, MetadataHandler>> providerList = new ArrayList<>();
    //noinspection unchecked
    final ReflectiveRelMetadataProvider.Space space = new ReflectiveRelMetadataProvider.Space((Multimap) map);
    for (MetadataHandler provider : space.providerMap.values()) {
        if (providerSet.add(provider)) {
            providerList.add(Pair.of("provider" + (providerSet.size() - 1), provider));
        }/*from   w ww.ja  v a 2 s.c  o m*/
    }

    buff.append("  private final java.util.List relClasses;\n");
    for (Pair<String, MetadataHandler> pair : providerList) {
        buff.append("  public final ").append(pair.right.getClass().getName()).append(' ').append(pair.left)
                .append(";\n");
    }
    buff.append("  public ").append(name).append("(java.util.List relClasses");
    for (Pair<String, MetadataHandler> pair : providerList) {
        buff.append(",\n").append("      ").append(pair.right.getClass().getName()).append(' ')
                .append(pair.left);
    }
    buff.append(") {\n").append("    this.relClasses = relClasses;\n");

    for (Pair<String, MetadataHandler> pair : providerList) {
        buff.append("    this.").append(pair.left).append(" = ").append(pair.left).append(";\n");
    }
    buff.append("  }\n").append("  public ").append(MetadataDef.class.getName()).append(" getDef() {\n")
            .append("    return ").append(def.metadataClass.getName()).append(".DEF;\n").append("  }\n");
    for (Ord<Method> method : Ord.zip(def.methods)) {
        buff.append("  public ").append(method.e.getReturnType().getName()).append(" ")
                .append(method.e.getName()).append("(\n").append("      ").append(RelNode.class.getName())
                .append(" r,\n").append("      ").append(RelMetadataQuery.class.getName()).append(" mq");
        paramList(buff, method.e).append(") {\n");
        buff.append("    final java.util.List key = ")
                .append((method.e.getParameterTypes().length < 4 ? org.apache.calcite.runtime.FlatLists.class
                        : ImmutableList.class).getName())
                .append(".of(").append(def.metadataClass.getName());
        if (method.i == 0) {
            buff.append(".DEF");
        } else {
            buff.append(".DEF.methods.get(").append(method.i).append(")");
        }
        buff.append(", r");
        safeArgList(buff, method.e).append(");\n").append("    final Object v = mq.map.get(key);\n")
                .append("    if (v != null) {\n").append("      if (v == ").append(NullSentinel.class.getName())
                .append(".ACTIVE) {\n").append("        throw ").append(CyclicMetadataException.class.getName())
                .append(".INSTANCE;\n").append("      }\n").append("      return (")
                .append(method.e.getReturnType().getName()).append(") v;\n").append("    }\n")
                .append("    mq.map.put(key,").append(NullSentinel.class.getName()).append(".ACTIVE);\n")
                .append("    try {\n").append("      final ").append(method.e.getReturnType().getName())
                .append(" x = ").append(method.e.getName()).append("_(r, mq");
        argList(buff, method.e).append(");\n").append("      mq.map.put(key, x);\n").append("      return x;\n")
                .append("    } catch (").append(NoHandler.class.getName()).append(" e) {\n")
                .append("      mq.map.remove(key);\n").append("      throw e;\n").append("    }\n")
                .append("  }\n").append("\n").append("  private ").append(method.e.getReturnType().getName())
                .append(" ").append(method.e.getName()).append("_(\n").append("      ")
                .append(RelNode.class.getName()).append(" r,\n").append("      ")
                .append(RelMetadataQuery.class.getName()).append(" mq");
        paramList(buff, method.e).append(") {\n");
        buff.append("    switch (relClasses.indexOf(r.getClass())) {\n");

        // Build a list of clauses, grouping clauses that have the same action.
        final Multimap<String, Integer> clauses = LinkedHashMultimap.create();
        final StringBuilder buf2 = new StringBuilder();
        for (Ord<Class<? extends RelNode>> relClass : Ord.zip(relClasses)) {
            if (relClass.e == HepRelVertex.class) {
                buf2.append("      return ").append(method.e.getName()).append("(((")
                        .append(relClass.e.getName()).append(") r).getCurrentRel(), mq");
                argList(buf2, method.e).append(");\n");
            } else {
                final Method handler = space.find(relClass.e, method.e);
                final String v = findProvider(providerList, handler.getDeclaringClass());
                buf2.append("      return ").append(v).append(".").append(method.e.getName()).append("((")
                        .append(handler.getParameterTypes()[0].getName()).append(") r, mq");
                argList(buf2, method.e).append(");\n");
            }
            clauses.put(buf2.toString(), relClass.i);
            buf2.setLength(0);
        }
        buf2.append("      throw new ").append(NoHandler.class.getName()).append("(r.getClass());\n")
                .append("    }\n").append("  }\n");
        clauses.put(buf2.toString(), -1);
        for (Map.Entry<String, Collection<Integer>> pair : clauses.asMap().entrySet()) {
            if (pair.getValue().contains(relClasses.indexOf(RelNode.class))) {
                buff.append("    default:\n");
            } else {
                for (Integer integer : pair.getValue()) {
                    buff.append("    case ").append(integer).append(":\n");
                }
            }
            buff.append(pair.getKey());
        }
    }
    ClassDeclaration decl = new ClassDeclaration(0, name, Object.class, ImmutableList.<Type>of(),
            ImmutableList.<MemberDeclaration>of());
    final List<Object> argList = new ArrayList<Object>(Pair.right(providerList));
    argList.add(0, ImmutableList.copyOf(relClasses));
    try {
        return compile(decl, buff.toString(), def, argList);
    } catch (CompileException | IOException e) {
        throw new RuntimeException("Error compiling:\n" + buff, e);
    }
}

From source file:com.google.devtools.build.lib.syntax.BaseFunction.java

/**
 * Process the caller-provided arguments into an array suitable for the callee (this function).
 */// w w  w  .ja  va  2s  .co  m
public Object[] processArguments(List<Object> args, @Nullable Map<String, Object> kwargs,
        @Nullable Location loc, @Nullable Environment env) throws EvalException {

    Object[] arguments = new Object[getArgArraySize()];

    // extract function signature
    FunctionSignature sig = signature.getSignature();
    FunctionSignature.Shape shape = sig.getShape();
    ImmutableList<String> names = sig.getNames();
    List<Object> defaultValues = signature.getDefaultValues();

    // Note that this variable will be adjusted down if there are extra positionals,
    // after these extra positionals are dumped into starParam.
    int numPositionalArgs = args.size();

    int numMandatoryPositionalParams = shape.getMandatoryPositionals();
    int numOptionalPositionalParams = shape.getOptionalPositionals();
    int numMandatoryNamedOnlyParams = shape.getMandatoryNamedOnly();
    int numOptionalNamedOnlyParams = shape.getOptionalNamedOnly();
    boolean hasStarParam = shape.hasStarArg();
    boolean hasKwParam = shape.hasKwArg();
    int numPositionalParams = numMandatoryPositionalParams + numOptionalPositionalParams;
    int numNamedOnlyParams = numMandatoryNamedOnlyParams + numOptionalNamedOnlyParams;
    int numNamedParams = numPositionalParams + numNamedOnlyParams;
    int kwParamIndex = names.size() - 1; // only valid if hasKwParam

    // (1) handle positional arguments
    if (hasStarParam) {
        // Nota Bene: we collect extra positional arguments in a (tuple,) rather than a [list],
        // and this is actually the same as in Python.
        int starParamIndex = numNamedParams;
        if (numPositionalArgs > numPositionalParams) {
            arguments[starParamIndex] = Tuple.copyOf(args.subList(numPositionalParams, numPositionalArgs));
            numPositionalArgs = numPositionalParams; // clip numPositionalArgs
        } else {
            arguments[starParamIndex] = Tuple.empty();
        }
    } else if (numPositionalArgs > numPositionalParams) {
        throw new EvalException(loc,
                numPositionalParams > 0
                        ? "too many (" + numPositionalArgs + ") positional arguments in call to " + this
                        : this + " does not accept positional arguments, but got " + numPositionalArgs);
    }

    for (int i = 0; i < numPositionalArgs; i++) {
        arguments[i] = args.get(i);
    }

    // (2) handle keyword arguments
    if (kwargs == null || kwargs.isEmpty()) {
        // Easy case (2a): there are no keyword arguments.
        // All arguments were positional, so check we had enough to fill all mandatory positionals.
        if (numPositionalArgs < numMandatoryPositionalParams) {
            throw new EvalException(loc,
                    String.format("insufficient arguments received by %s (got %s, expected at least %s)", this,
                            numPositionalArgs, numMandatoryPositionalParams));
        }
        // We had no named argument, so fail if there were mandatory named-only parameters
        if (numMandatoryNamedOnlyParams > 0) {
            throw new EvalException(loc,
                    String.format("missing mandatory keyword arguments in call to %s", this));
        }
        // Fill in defaults for missing optional parameters, that were conveniently grouped together,
        // thanks to the absence of mandatory named-only parameters as checked above.
        if (defaultValues != null) {
            int j = numPositionalArgs - numMandatoryPositionalParams;
            int endOptionalParams = numPositionalParams + numOptionalNamedOnlyParams;
            for (int i = numPositionalArgs; i < endOptionalParams; i++) {
                arguments[i] = defaultValues.get(j++);
            }
        }
        // If there's a kwParam, it's empty.
        if (hasKwParam) {
            // TODO(bazel-team): create a fresh mutable dict, like Python does
            arguments[kwParamIndex] = SkylarkDict.of(env);
        }
    } else if (hasKwParam && numNamedParams == 0) {
        // Easy case (2b): there are no named parameters, but there is a **kwParam.
        // Therefore all keyword arguments go directly to the kwParam.
        // Note that *starParam and **kwParam themselves don't count as named.
        // Also note that no named parameters means no mandatory parameters that weren't passed,
        // and no missing optional parameters for which to use a default. Thus, no loops.
        // NB: not 2a means kwarg isn't null
        arguments[kwParamIndex] = SkylarkDict.copyOf(env, kwargs);
    } else {
        // Hard general case (2c): some keyword arguments may correspond to named parameters
        SkylarkDict<String, Object> kwArg = hasKwParam ? SkylarkDict.<String, Object>of(env)
                : SkylarkDict.<String, Object>empty();

        // For nicer stabler error messages, start by checking against
        // an argument being provided both as positional argument and as keyword argument.
        ArrayList<String> bothPosKey = new ArrayList<>();
        for (int i = 0; i < numPositionalArgs; i++) {
            String name = names.get(i);
            if (kwargs.containsKey(name)) {
                bothPosKey.add(name);
            }
        }
        if (!bothPosKey.isEmpty()) {
            throw new EvalException(loc,
                    String.format("argument%s '%s' passed both by position and by name in call to %s",
                            (bothPosKey.size() > 1 ? "s" : ""), Joiner.on("', '").join(bothPosKey), this));
        }

        // Accept the arguments that were passed.
        for (Map.Entry<String, Object> entry : kwargs.entrySet()) {
            String keyword = entry.getKey();
            Object value = entry.getValue();
            int pos = names.indexOf(keyword); // the list should be short, so linear scan is OK.
            if (0 <= pos && pos < numNamedParams) {
                arguments[pos] = value;
            } else {
                if (!hasKwParam) {
                    List<String> unexpected = Ordering.natural().sortedCopy(Sets.difference(kwargs.keySet(),
                            ImmutableSet.copyOf(names.subList(0, numNamedParams))));
                    throw new EvalException(loc, String.format("unexpected keyword%s '%s' in call to %s",
                            unexpected.size() > 1 ? "s" : "", Joiner.on("', '").join(unexpected), this));
                }
                if (kwArg.containsKey(keyword)) {
                    throw new EvalException(loc,
                            String.format("%s got multiple values for keyword argument '%s'", this, keyword));
                }
                kwArg.put(keyword, value, loc, env);
            }
        }
        if (hasKwParam) {
            // TODO(bazel-team): create a fresh mutable dict, like Python does
            arguments[kwParamIndex] = SkylarkDict.copyOf(env, kwArg);
        }

        // Check that all mandatory parameters were filled in general case 2c.
        // Note: it's possible that numPositionalArgs > numMandatoryPositionalParams but that's OK.
        for (int i = numPositionalArgs; i < numMandatoryPositionalParams; i++) {
            if (arguments[i] == null) {
                throw new EvalException(loc, String.format(
                        "missing mandatory positional argument '%s' while calling %s", names.get(i), this));
            }
        }

        int endMandatoryNamedOnlyParams = numPositionalParams + numMandatoryNamedOnlyParams;
        for (int i = numPositionalParams; i < endMandatoryNamedOnlyParams; i++) {
            if (arguments[i] == null) {
                throw new EvalException(loc, String.format(
                        "missing mandatory named-only argument '%s' while calling %s", names.get(i), this));
            }
        }

        // Get defaults for those parameters that weren't passed.
        if (defaultValues != null) {
            for (int i = Math.max(numPositionalArgs,
                    numMandatoryPositionalParams); i < numPositionalParams; i++) {
                if (arguments[i] == null) {
                    arguments[i] = defaultValues.get(i - numMandatoryPositionalParams);
                }
            }
            int numMandatoryParams = numMandatoryPositionalParams + numMandatoryNamedOnlyParams;
            for (int i = numMandatoryParams + numOptionalPositionalParams; i < numNamedParams; i++) {
                if (arguments[i] == null) {
                    arguments[i] = defaultValues.get(i - numMandatoryParams);
                }
            }
        }
    } // End of general case 2c for argument passing.

    return arguments;
}