/*
* Copyright 2000-2013 JetBrains s.r.o.
* Copyright 2014-2015 AS3Boyan
* Copyright 2014-2014 Elias Ku
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.plugins.haxe.model.type;
import com.intellij.plugins.haxe.lang.psi.HaxeClass;
import com.intellij.plugins.haxe.lang.psi.impl.AbstractHaxeNamedComponent;
import com.intellij.plugins.haxe.model.HaxeClassModel;
import com.intellij.plugins.haxe.model.HaxeGenericParamModel;
import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.List;
public class SpecificHaxeClassReference extends SpecificTypeReference {
static public SpecificHaxeClassReference[] EMPTY = new SpecificHaxeClassReference[0];
@NotNull final public HaxeClassReference clazz;
// @TODO: Change specifics with generics + generic resolver?
final public ResultHolder[] specifics;
final public Object constantValue;
final public HaxeRange rangeConstraint;
public SpecificHaxeClassReference(
@NotNull HaxeClassReference clazz,
ResultHolder[] specifics,
Object constantValue,
HaxeRange rangeConstraint,
@NotNull PsiElement context
) {
super(context);
this.clazz = clazz;
this.specifics = specifics;
this.constantValue = constantValue;
this.rangeConstraint = rangeConstraint;
}
public HaxeClassReference getHaxeClassRef() {
return this.clazz;
}
public HaxeClass getHaxeClass() {
return this.clazz.getHaxeClass();
}
public HaxeClassModel getHaxeClassModel() {
final HaxeClass aClass = getHaxeClass();
;
return (aClass != null) ? aClass.getModel() : null;
}
public SpecificHaxeClassReference withConstantValue(Object constantValue) {
//if (this.constantValue == constantValue) return this;
return new SpecificHaxeClassReference(clazz, specifics.clone(), constantValue, null, context);
}
//@Override
//public void mutateConstantValue(Object constantValue) {
// this.constantValue = constantValue;
//}
@Override
public SpecificTypeReference withRangeConstraint(HaxeRange range) {
if (this.rangeConstraint == range) return this;
return new SpecificHaxeClassReference(clazz, specifics.clone(), constantValue, range, context);
}
@Override
public HaxeRange getRangeConstraint() {
return this.rangeConstraint;
}
@Override
public Object getConstant() {
return this.constantValue;
}
static public SpecificHaxeClassReference withoutGenerics(@NotNull HaxeClassReference clazz) {
return new SpecificHaxeClassReference(clazz, ResultHolder.EMPTY, null, null, clazz.elementContext);
}
static public SpecificHaxeClassReference withoutGenerics(@NotNull HaxeClassReference clazz, Object constantValue) {
return new SpecificHaxeClassReference(clazz, ResultHolder.EMPTY, constantValue, null, clazz.elementContext);
}
static public SpecificHaxeClassReference withGenerics(@NotNull HaxeClassReference clazz, ResultHolder[] specifics) {
return new SpecificHaxeClassReference(clazz, specifics, null, null, clazz.elementContext);
}
static public SpecificHaxeClassReference withGenerics(@NotNull HaxeClassReference clazz, ResultHolder[] specifics, Object constantValue) {
return new SpecificHaxeClassReference(clazz, specifics, constantValue, null, clazz.elementContext);
}
public String toStringWithoutConstant() {
String out = this.clazz.getName();
if (specifics.length > 0) {
out += "<";
for (int n = 0; n < specifics.length; n++) {
if (n > 0) out += ", ";
out += specifics[n].toString();
}
out += ">";
}
return out;
}
public String toStringWithConstant() {
String out = toStringWithoutConstant();
if (constantValue != null) {
if (out.equals("Int")) {
out += " = " + (int)HaxeTypeUtils.getDoubleValue(constantValue);
}
else if (out.equals("String")) {
out += " = " + constantValue + "";
}
else {
out += " = " + constantValue;
}
}
if (rangeConstraint != null) {
out += " [" + rangeConstraint + "]";
}
return out;
}
@Override
public String toString() {
//return toStringWithoutConstant();
return toStringWithConstant();
}
public HaxeGenericResolver getGenericResolver() {
HaxeGenericResolver resolver = new HaxeGenericResolver();
HaxeClassModel model = getHaxeClassModel();
if (model != null) {
List<HaxeGenericParamModel> params = model.getGenericParams();
for (int n = 0; n < params.size(); n++) {
HaxeGenericParamModel paramModel = params.get(n);
ResultHolder specific = (n < specifics.length) ? this.specifics[n] : getUnknown(context).createHolder();
resolver.resolvers.put(paramModel.getName(), specific);
}
}
return resolver;
}
@Nullable
@Override
public ResultHolder access(String name, HaxeExpressionEvaluatorContext context) {
if (this.isDynamic()) return this.withoutConstantValue().createHolder();
if (name == null) {
return null;
}
HaxeClass aClass = this.clazz.getHaxeClass();
if (aClass == null) {
return null;
}
AbstractHaxeNamedComponent field = (AbstractHaxeNamedComponent)aClass.findHaxeFieldByName(name);
AbstractHaxeNamedComponent method = (AbstractHaxeNamedComponent)aClass.findHaxeMethodByName(name);
if (method != null) {
if (context.root == method) return null;
return HaxeTypeResolver.getMethodFunctionType(method, getGenericResolver());
}
if (field != null) {
if (context.root == field) return null;
return HaxeTypeResolver.getFieldOrMethodReturnType(field, getGenericResolver());
}
return null;
}
}