/* * Copyright 2000-2013 JetBrains s.r.o. * * 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.coldFusion.model.psi; import com.intellij.coldFusion.model.parsers.CfmlElementTypes; import com.intellij.lang.ASTNode; import com.intellij.psi.*; import com.intellij.psi.impl.source.PsiClassReferenceType; import com.intellij.util.ArrayUtil; import com.intellij.util.Function; import com.intellij.util.NullableFunction; import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; /** * Created by Lera Nikolaenko * Date: 24.02.2009 */ public class CfmlFunctionCallExpression extends CfmlCompositeElement implements CfmlExpression, CfmlFunctionCall, CfmlTypedElement { public CfmlFunctionCallExpression(final ASTNode node) { super(node); } public boolean isCreateFromJavaLoader() { PsiElement firstChild = findChildByType(CfmlElementTypes.REFERENCE_EXPRESSION); if (firstChild == null) { return false; } PsiElement lastChild = firstChild.getLastChild(); if (lastChild == null) { return false; } String create = lastChild.getText(); PsiElement secondChild = firstChild.getFirstChild(); if (!(create.toLowerCase().equals("create") && secondChild instanceof CfmlReferenceExpression)) { return false; } PsiType type = ((CfmlReferenceExpression)secondChild).getPsiType(); if (type == null) { return false; } return type.getCanonicalText().toLowerCase().equals("javaloader"); } public class PsiClassStaticType extends PsiClassReferenceType { private String myClassName; public PsiClassStaticType(final PsiJavaCodeReferenceElement reference, String className) { super(reference, null); myClassName = className; } @Nullable public PsiType getRawType() { return CfmlPsiUtil.getTypeByName(myClassName, getProject()); } } @Nullable public PsiType getExternalType() { String functionName = getFunctionName(); final CfmlReference referenceExpression = getReferenceExpression(); // createObject specific code if ("createobject".equals(functionName.toLowerCase())) { final CfmlArgumentList cfmlArgumentList = findArgumentList(); if (cfmlArgumentList == null) { return null; } CfmlExpression[] argumentsList = cfmlArgumentList.getArguments(); if (argumentsList.length == 0) { return null; } if (argumentsList[0] instanceof CfmlStringLiteralExpression) { final String secondParameterName = ((CfmlStringLiteralExpression)argumentsList[0]).getValue().toLowerCase(); if ("java".equals(secondParameterName) && argumentsList.length >= 2) { String className = argumentsList[1].getText(); className = className.substring(1, className.length() - 1); final PsiJavaCodeReferenceElement reference = JavaPsiFacade.getInstance(getProject()).getElementFactory().createReferenceElementByFQClassName(className, getResolveScope()); return new PsiClassStaticType(reference, className); } else if (("component".equals(secondParameterName) && argumentsList.length >= 2) || (argumentsList.length == 1)) { final PsiReference[] references = argumentsList[argumentsList.length == 1 ? 0 : 1].getReferences(); if (references.length != 0 && references[0] instanceof CfmlComponentReference) { final CfmlComponentReference componentRef = ((CfmlComponentReference)references[0]); if (componentRef != null) { return new CfmlComponentType(componentRef.getText(), getContainingFile(), getProject()); } } } } } else if ("init".equals(getFunctionShortName().toLowerCase())) { CfmlReference qualifier = CfmlPsiUtil.getQualifierInner(this); CfmlReference sourceObject = CfmlPsiUtil.getQualifierInner(qualifier); if (sourceObject != null) { final PsiType type = sourceObject.getPsiType(); if (type instanceof PsiClassStaticType) { return ((PsiClassStaticType)type).getRawType(); } if (type instanceof CfmlComponentType) { return type; } } } else if (isCreateFromJavaLoader()) { CfmlArgumentList argumentList = findArgumentList(); if (argumentList == null) { return null; } CfmlExpression[] argumentsList = argumentList.getArguments(); if (argumentsList.length == 0) { return null; } String className = argumentsList[0].getText(); className = className.substring(1, className.length() - 1); return CfmlPsiUtil.getTypeByName(className, getProject()); } else if (referenceExpression != null) { final PsiElement resolve = referenceExpression.resolve(); return resolve instanceof CfmlFunction ? ((CfmlFunction)resolve).getReturnType() : null; } return null; } @Nullable public PsiType getPsiType() { PsiType externalType = getExternalType(); if (externalType == null) { CfmlReference referenceExpression = getReferenceExpression(); return referenceExpression != null ? referenceExpression.getPsiType() : null; } return externalType; } @NotNull public CfmlExpression[] getArguments() { CfmlArgumentList argumentListEl = findChildByClass(CfmlArgumentList.class); if (argumentListEl == null) { return new CfmlExpression[0]; } return argumentListEl.getArguments(); } @NotNull public String[] getArgumentsAsStrings() { CfmlArgumentList argumentListEl = findChildByClass(CfmlArgumentList.class); if (argumentListEl == null) { return ArrayUtil.EMPTY_STRING_ARRAY; } final CfmlExpression[] args = argumentListEl.getArguments(); return ContainerUtil.map(args, cfmlExpression -> { if (cfmlExpression instanceof CfmlStringLiteralExpression) { return ((CfmlStringLiteralExpression)cfmlExpression).getValue().toLowerCase(); } return ""; }, ArrayUtil.EMPTY_STRING_ARRAY); } public String getFunctionShortName() { CfmlReference referenceExpression = getReferenceExpression(); if (referenceExpression == null) { return ""; } final PsiElement child = referenceExpression.getLastChild(); return child != null ? child.getText() : ""; } public String getFunctionName() { String functionName = ""; CfmlReference referenceExpression = getReferenceExpression(); if (referenceExpression != null && referenceExpression.getText() != null) { functionName = referenceExpression.getText(); } return functionName; } public boolean isCreateObject() { return getFunctionName().toLowerCase().equals("createobject"); } public boolean isExpandPath() { return getFunctionName().toLowerCase().equals("expandpath"); } @Nullable public CfmlReference getReferenceExpression() { return findChildByClass(CfmlReferenceExpression.class); } @Nullable public CfmlArgumentList findArgumentList() { return findChildByClass(CfmlArgumentList.class); } public PsiType[] getArgumentTypes() { CfmlArgumentList argumentsList = findArgumentList(); if (argumentsList == null) { return PsiType.EMPTY_ARRAY; } CfmlExpression[] args = argumentsList.getArguments(); return ContainerUtil.map2Array(args, PsiType.class, (NullableFunction<CfmlExpression, PsiType>)expression -> expression.getPsiType()); } }