001/*
002 * Copyright 2010-2013 JetBrains s.r.o.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016
017package org.jetbrains.k2js.translate.reference;
018
019import com.google.common.collect.Lists;
020import com.google.dart.compiler.backend.js.ast.JsExpression;
021import org.jetbrains.annotations.NotNull;
022import org.jetbrains.annotations.Nullable;
023import org.jetbrains.jet.lang.descriptors.CallableDescriptor;
024import org.jetbrains.jet.lang.resolve.BindingTraceContext;
025import org.jetbrains.jet.lang.resolve.DescriptorUtils;
026import org.jetbrains.jet.lang.resolve.TemporaryBindingTrace;
027import org.jetbrains.jet.lang.resolve.calls.tasks.ExplicitReceiverKind;
028import org.jetbrains.jet.lang.resolve.calls.tasks.ResolutionCandidate;
029import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall;
030import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCallImpl;
031import org.jetbrains.jet.lang.resolve.calls.tasks.TracingStrategy;
032import org.jetbrains.k2js.translate.context.TranslationContext;
033
034import java.util.Arrays;
035import java.util.List;
036
037public final class CallBuilder {
038
039    public static CallBuilder build(@NotNull TranslationContext context) {
040        return new CallBuilder(context);
041    }
042
043    @NotNull
044    private final TranslationContext context;
045    @Nullable
046    private /*var*/ JsExpression receiver = null;
047    @NotNull
048    private final List<JsExpression> args = Lists.newArrayList();
049    @NotNull
050    private /*var*/ CallType callType = CallType.NORMAL;
051    @Nullable
052    private /*var*/ ResolvedCall<?> resolvedCall = null;
053    @Nullable
054    private  /*var*/ CallableDescriptor descriptor = null;
055    @Nullable
056    private /*var*/ JsExpression callee = null;
057
058
059    private CallBuilder(@NotNull TranslationContext context) {
060        this.context = context;
061    }
062
063    @NotNull
064    public CallBuilder receiver(@Nullable JsExpression receiver) {
065        this.receiver = receiver;
066        return this;
067    }
068
069    @NotNull
070    public CallBuilder args(@NotNull List<JsExpression> args) {
071        assert this.args.isEmpty();
072        this.args.addAll(args);
073        return this;
074    }
075
076    @NotNull
077    public CallBuilder args(@NotNull JsExpression... args) {
078        return args(Arrays.asList(args));
079    }
080
081    @NotNull
082    public CallBuilder descriptor(@NotNull CallableDescriptor descriptor) {
083        this.descriptor = descriptor;
084        return this;
085    }
086
087    @NotNull
088    public CallBuilder callee(@Nullable JsExpression callee) {
089        this.callee = callee;
090        return this;
091    }
092
093    @NotNull
094    public CallBuilder resolvedCall(@NotNull ResolvedCall<?> call) {
095        this.resolvedCall = call;
096        return this;
097    }
098
099    @NotNull
100    public CallBuilder type(@NotNull CallType type) {
101        this.callType = type;
102        return this;
103    }
104
105    @NotNull
106    private CallTranslator finish() {
107        if (resolvedCall == null) {
108            assert descriptor != null;
109            resolvedCall = ResolvedCallImpl.create(ResolutionCandidate.create(descriptor, DescriptorUtils.safeGetValue(descriptor.getExpectedThisObject()),
110                                                                              DescriptorUtils.safeGetValue(descriptor.getReceiverParameter()),
111                                                                              ExplicitReceiverKind.THIS_OBJECT, false),
112                                                   TemporaryBindingTrace.create(new BindingTraceContext(), "trace to resolve call (in js)"),
113                                                   TracingStrategy.EMPTY);
114        }
115        if (descriptor == null) {
116            descriptor = resolvedCall.getCandidateDescriptor().getOriginal();
117        }
118        assert resolvedCall != null;
119        return new CallTranslator(receiver, callee, args, resolvedCall, descriptor, callType, context);
120    }
121
122    @NotNull
123    public JsExpression translate() {
124        return finish().translate();
125    }
126
127
128}