/*
* 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.psi.PsiElement;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public abstract class SpecificTypeReference {
final protected PsiElement context;
public SpecificTypeReference(@NotNull PsiElement context) {
this.context = context;
}
static public SpecificTypeReference createArray(@NotNull ResultHolder elementType) {
return SpecificHaxeClassReference
.withGenerics(new HaxeClassReference("Array", elementType.getElementContext()), new ResultHolder[]{elementType}, null);
}
public SpecificTypeReference withRangeConstraint(HaxeRange range) {
return this;
}
static public SpecificHaxeClassReference getVoid(@NotNull PsiElement context) {
return primitive("Void", context);
}
static public SpecificHaxeClassReference getBool(@NotNull PsiElement context) {
return primitive("Bool", context);
}
static public SpecificHaxeClassReference getInt(@NotNull PsiElement context) {
return primitive("Int", context);
}
static public SpecificHaxeClassReference getInt(@NotNull PsiElement context, int value) {
return primitive("Int", context, value);
}
static public SpecificHaxeClassReference getDynamic(@NotNull PsiElement context) {
return primitive("Dynamic", context);
}
static public SpecificHaxeClassReference getUnknown(@NotNull PsiElement context) {
return primitive("Unknown", context);
}
static public SpecificHaxeClassReference getInvalid(@NotNull PsiElement context) {
return primitive("@@Invalid", context);
}
static public SpecificHaxeClassReference getIterator(SpecificHaxeClassReference type) {
return SpecificHaxeClassReference.withGenerics(new HaxeClassReference("Iterator", type.getElementContext()),
new ResultHolder[]{type.createHolder()});
}
static public SpecificHaxeClassReference primitive(String name, @NotNull PsiElement context) {
return SpecificHaxeClassReference.withoutGenerics(new HaxeClassReference(name, context));
}
static public SpecificHaxeClassReference primitive(String name, @NotNull PsiElement context, Object constant) {
return SpecificHaxeClassReference.withoutGenerics(new HaxeClassReference(name, context), constant);
}
final public boolean isUnknown() {
return this.toStringWithoutConstant().equals("Unknown");
}
final public boolean isDynamic() {
return this.toStringWithoutConstant().equals("Dynamic");
}
final public boolean isInvalid() {
return this.toStringWithoutConstant().equals("@@Invalid");
}
final public boolean isVoid() {
return this.toStringWithoutConstant().equals("Void");
}
final public boolean isInt() {
return this.toStringWithoutConstant().equals("Int");
}
final public boolean isNumeric() {
return isInt() || isFloat();
}
final public boolean isBool() {
return this.toStringWithoutConstant().equals("Bool");
}
final public boolean isFloat() {
return this.toStringWithoutConstant().equals("Float");
}
final public boolean isString() {
return this.toStringWithoutConstant().equals("String");
}
final public boolean isArray() {
if (this instanceof SpecificHaxeClassReference) {
final SpecificHaxeClassReference reference = (SpecificHaxeClassReference)this;
return reference.clazz.getName().equals("Array");
}
return false;
}
final public ResultHolder getArrayElementType() {
if (isArray()) {
final ResultHolder[] specifics = ((SpecificHaxeClassReference)this).specifics;
if (specifics.length >= 1) return specifics[0];
}
return getUnknown(context).createHolder();
}
final public ResultHolder getIterableElementType(SpecificTypeReference iterable) {
if (isArray()) {
return getArrayElementType();
}
// @TODO: Must implement it (it is not int always)
return getInt(iterable.getElementContext()).createHolder();
}
abstract public SpecificTypeReference withConstantValue(Object constantValue);
//public void mutateConstantValue(Object constantValue) {
//
//}
final public SpecificTypeReference withoutConstantValue() {
return withConstantValue(null);
}
public boolean isConstant() {
return this.getConstant() != null;
}
public HaxeRange getRangeConstraint() {
return null;
}
public Object getConstant() {
return null;
}
final public boolean getConstantAsBool() {
return HaxeTypeUtils.getBoolValue(getConstant());
}
final public double getConstantAsDouble() {
return HaxeTypeUtils.getDoubleValue(getConstant());
}
final public int getConstantAsInt() {
return HaxeTypeUtils.getIntValue(getConstant());
}
@NotNull
final public PsiElement getElementContext() {
return context;
}
abstract public String toString();
abstract public String toStringWithoutConstant();
public String toStringWithConstant() {
return toString();
}
@Nullable
public ResultHolder access(String name, HaxeExpressionEvaluatorContext context) {
return null;
}
final public boolean canAssign(SpecificTypeReference type2) {
return HaxeTypeCompatible.canAssignToFrom(this, type2);
}
final public boolean canAssign(ResultHolder type2) {
return HaxeTypeCompatible.canAssignToFrom(this, type2);
}
public ResultHolder createHolder() {
return new ResultHolder(this);
}
}