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.jet.lang.psi; 018 019import com.intellij.lang.ASTNode; 020import com.intellij.navigation.ItemPresentation; 021import com.intellij.navigation.ItemPresentationProviders; 022import com.intellij.psi.PsiElement; 023import com.intellij.psi.stubs.IStubElementType; 024import com.intellij.psi.tree.IElementType; 025import com.intellij.psi.util.PsiTreeUtil; 026import org.jetbrains.annotations.NotNull; 027import org.jetbrains.annotations.Nullable; 028import org.jetbrains.jet.JetNodeTypes; 029import org.jetbrains.jet.lang.psi.stubs.PsiJetFunctionStub; 030import org.jetbrains.jet.lang.psi.stubs.elements.JetStubElementTypes; 031import org.jetbrains.jet.lang.resolve.name.FqName; 032import org.jetbrains.jet.lang.resolve.name.Name; 033import org.jetbrains.jet.lexer.JetTokens; 034 035import java.util.Collections; 036import java.util.List; 037 038public class JetNamedFunction extends JetTypeParameterListOwnerStub<PsiJetFunctionStub> implements JetFunction, JetWithExpressionInitializer { 039 public JetNamedFunction(@NotNull ASTNode node) { 040 super(node); 041 } 042 043 public JetNamedFunction(@NotNull PsiJetFunctionStub stub) { 044 super(stub, JetStubElementTypes.FUNCTION); 045 } 046 047 @Override 048 public void accept(@NotNull JetVisitorVoid visitor) { 049 visitor.visitNamedFunction(this); 050 } 051 052 @Override 053 public <R, D> R accept(@NotNull JetVisitor<R, D> visitor, D data) { 054 return visitor.visitNamedFunction(this, data); 055 } 056 057 public boolean hasTypeParameterListBeforeFunctionName() { 058 JetTypeParameterList typeParameterList = getTypeParameterList(); 059 if (typeParameterList == null) { 060 return false; 061 } 062 PsiElement nameIdentifier = getNameIdentifier(); 063 if (nameIdentifier == null) { 064 return false; 065 } 066 return nameIdentifier.getTextOffset() > typeParameterList.getTextOffset(); 067 } 068 069 @Override 070 public boolean hasBlockBody() { 071 return getEqualsToken() == null; 072 } 073 074 @Nullable 075 public PsiElement getEqualsToken() { 076 return findChildByType(JetTokens.EQ); 077 } 078 079 @Override 080 @Nullable 081 public JetExpression getInitializer() { 082 return PsiTreeUtil.getNextSiblingOfType(getEqualsToken(), JetExpression.class); 083 } 084 085 /** 086 * Returns full qualified name for function "package_fqn.function_name" 087 * Not null for top level functions unless syntax errors are present. 088 * @return 089 */ 090 @Nullable 091 public FqName getFqName() { 092 PsiJetFunctionStub stub = getStub(); 093 if (stub != null) { 094 return stub.getTopFQName(); 095 } 096 097 PsiElement parent = getParent(); 098 if (parent instanceof JetFile) { 099 // fqname is different in scripts 100 if (((JetFile) parent).getNamespaceHeader() == null) { 101 return null; 102 } 103 JetFile jetFile = (JetFile) parent; 104 FqName fileFQN = JetPsiUtil.getFQName(jetFile); 105 Name nameAsName = getNameAsName(); 106 if (nameAsName != null) { 107 return fileFQN.child(nameAsName); 108 } 109 } 110 111 return null; 112 } 113 114 @NotNull 115 @Override 116 public IStubElementType getElementType() { 117 return JetStubElementTypes.FUNCTION; 118 } 119 120 @Override 121 public ItemPresentation getPresentation() { 122 return ItemPresentationProviders.getItemPresentation(this); 123 } 124 125 @Override 126 @Nullable 127 public JetParameterList getValueParameterList() { 128 return (JetParameterList) findChildByType(JetNodeTypes.VALUE_PARAMETER_LIST); 129 } 130 131 @Override 132 @NotNull 133 public List<JetParameter> getValueParameters() { 134 JetParameterList list = getValueParameterList(); 135 return list != null ? list.getParameters() : Collections.<JetParameter>emptyList(); 136 } 137 138 @Override 139 @Nullable 140 public JetExpression getBodyExpression() { 141 return findChildByClass(JetExpression.class); 142 } 143 144 @Override 145 public boolean hasDeclaredReturnType() { 146 return getReturnTypeRef() != null; 147 } 148 149 @Override 150 @Nullable 151 public JetTypeReference getReceiverTypeRef() { 152 PsiElement child = getFirstChild(); 153 while (child != null) { 154 IElementType tt = child.getNode().getElementType(); 155 if (tt == JetTokens.LPAR || tt == JetTokens.COLON) break; 156 if (child instanceof JetTypeReference) { 157 return (JetTypeReference) child; 158 } 159 child = child.getNextSibling(); 160 } 161 162 return null; 163 } 164 165 @Override 166 @Nullable 167 public JetTypeReference getReturnTypeRef() { 168 boolean colonPassed = false; 169 PsiElement child = getFirstChild(); 170 while (child != null) { 171 IElementType tt = child.getNode().getElementType(); 172 if (tt == JetTokens.COLON) { 173 colonPassed = true; 174 } 175 if (colonPassed && child instanceof JetTypeReference) { 176 return (JetTypeReference) child; 177 } 178 child = child.getNextSibling(); 179 } 180 181 return null; 182 } 183 184 @NotNull 185 @Override 186 public JetElement asElement() { 187 return this; 188 } 189 190 @Override 191 public boolean isLocal() { 192 PsiElement parent = getParent(); 193 return !(parent instanceof JetFile || parent instanceof JetClassBody); 194 } 195}