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    
017    package org.jetbrains.k2js.translate.reference;
018    
019    import com.google.dart.compiler.backend.js.ast.JsExpression;
020    import org.jetbrains.annotations.NotNull;
021    import org.jetbrains.annotations.Nullable;
022    import org.jetbrains.jet.lang.descriptors.CallableDescriptor;
023    import org.jetbrains.jet.lang.descriptors.ReceiverParameterDescriptor;
024    import org.jetbrains.jet.lang.resolve.BindingTraceContext;
025    import org.jetbrains.jet.lang.resolve.TemporaryBindingTrace;
026    import org.jetbrains.jet.lang.resolve.calls.model.MutableDataFlowInfoForArguments;
027    import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall;
028    import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCallImpl;
029    import org.jetbrains.jet.lang.resolve.calls.tasks.ExplicitReceiverKind;
030    import org.jetbrains.jet.lang.resolve.calls.tasks.ResolutionCandidate;
031    import org.jetbrains.jet.lang.resolve.calls.tasks.TracingStrategy;
032    import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue;
033    import org.jetbrains.k2js.translate.context.TranslationContext;
034    
035    import java.util.Arrays;
036    import java.util.Collections;
037    import java.util.List;
038    
039    public final class CallBuilder {
040    
041        public static CallBuilder build(@NotNull TranslationContext context) {
042            return new CallBuilder(context);
043        }
044    
045        @NotNull
046        private final TranslationContext context;
047        @Nullable
048        private /*var*/ JsExpression receiver = null;
049        @NotNull
050        private List<JsExpression> args = Collections.emptyList();
051        @NotNull
052        private /*var*/ CallType callType = CallType.NORMAL;
053        @Nullable
054        private /*var*/ ResolvedCall<?> resolvedCall = null;
055        @Nullable
056        private  /*var*/ CallableDescriptor descriptor = null;
057        @Nullable
058        private /*var*/ JsExpression callee = null;
059    
060    
061        private CallBuilder(@NotNull TranslationContext context) {
062            this.context = context;
063        }
064    
065        @NotNull
066        public CallBuilder receiver(@Nullable JsExpression receiver) {
067            this.receiver = receiver;
068            return this;
069        }
070    
071        @NotNull
072        public CallBuilder args(@NotNull List<JsExpression> args) {
073            assert this.args == Collections.EMPTY_LIST;
074            this.args = args;
075            return this;
076        }
077    
078        @NotNull
079        public CallBuilder args(@NotNull JsExpression... args) {
080            return args(Arrays.asList(args));
081        }
082    
083        @NotNull
084        public CallBuilder descriptor(@NotNull CallableDescriptor descriptor) {
085            this.descriptor = descriptor;
086            return this;
087        }
088    
089        @NotNull
090        public CallBuilder callee(@Nullable JsExpression callee) {
091            this.callee = callee;
092            return this;
093        }
094    
095        @NotNull
096        public CallBuilder resolvedCall(@NotNull ResolvedCall<?> call) {
097            this.resolvedCall = call;
098            return this;
099        }
100    
101        @NotNull
102        public CallBuilder type(@NotNull CallType type) {
103            this.callType = type;
104            return this;
105        }
106    
107        @NotNull
108        private CallTranslator finish() {
109            if (resolvedCall == null) {
110                assert descriptor != null;
111                resolvedCall = ResolvedCallImpl.create(ResolutionCandidate.create(descriptor, safeGetValue(descriptor.getExpectedThisObject()),
112                                                                                  safeGetValue(descriptor.getReceiverParameter()),
113                                                                                  ExplicitReceiverKind.THIS_OBJECT, false),
114                                                       TemporaryBindingTrace.create(new BindingTraceContext(), "trace to resolve call (in js)"),
115                                                       TracingStrategy.EMPTY,
116                                                       MutableDataFlowInfoForArguments.WITHOUT_ARGUMENTS_CHECK);
117            }
118            if (descriptor == null) {
119                descriptor = resolvedCall.getCandidateDescriptor().getOriginal();
120            }
121            assert resolvedCall != null;
122            return new CallTranslator(receiver, callee, args, resolvedCall, descriptor, callType, context);
123        }
124    
125        @NotNull
126        private static ReceiverValue safeGetValue(@Nullable ReceiverParameterDescriptor descriptor) {
127            return descriptor == null ? ReceiverValue.NO_RECEIVER : descriptor.getValue();
128        }
129    
130        @NotNull
131        public JsExpression translate() {
132            return finish().translate();
133        }
134    }