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.jet.lang.psi;
018
019 import com.intellij.lang.ASTNode;
020 import com.intellij.navigation.ItemPresentation;
021 import com.intellij.navigation.ItemPresentationProviders;
022 import com.intellij.psi.PsiElement;
023 import com.intellij.psi.tree.IElementType;
024 import com.intellij.psi.util.PsiTreeUtil;
025 import org.jetbrains.annotations.NotNull;
026 import org.jetbrains.annotations.Nullable;
027 import org.jetbrains.jet.lang.psi.stubs.PsiJetFunctionStub;
028 import org.jetbrains.jet.lang.psi.stubs.elements.JetStubElementTypes;
029 import org.jetbrains.jet.lang.psi.typeRefHelpers.TypeRefHelpersPackage;
030 import org.jetbrains.jet.lexer.JetTokens;
031
032 import java.util.Collections;
033 import java.util.List;
034
035 public class JetNamedFunction extends JetTypeParameterListOwnerStub<PsiJetFunctionStub> implements JetFunction, JetWithExpressionInitializer {
036 public JetNamedFunction(@NotNull ASTNode node) {
037 super(node);
038 }
039
040 public JetNamedFunction(@NotNull PsiJetFunctionStub stub) {
041 super(stub, JetStubElementTypes.FUNCTION);
042 }
043
044 @Override
045 public <R, D> R accept(@NotNull JetVisitor<R, D> visitor, D data) {
046 return visitor.visitNamedFunction(this, data);
047 }
048
049 public boolean hasTypeParameterListBeforeFunctionName() {
050 PsiJetFunctionStub stub = getStub();
051 if (stub != null) {
052 return stub.hasTypeParameterListBeforeFunctionName();
053 }
054 return hasTypeParameterListBeforeFunctionNameByTree();
055 }
056
057 private boolean hasTypeParameterListBeforeFunctionNameByTree() {
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 PsiJetFunctionStub stub = getStub();
072 if (stub != null) {
073 return stub.hasBlockBody();
074 }
075 return getEqualsToken() == null;
076 }
077
078 @Nullable
079 public PsiElement getEqualsToken() {
080 return findChildByType(JetTokens.EQ);
081 }
082
083 @Override
084 @Nullable
085 public JetExpression getInitializer() {
086 return PsiTreeUtil.getNextSiblingOfType(getEqualsToken(), JetExpression.class);
087 }
088
089 @Override
090 public boolean hasInitializer() {
091 return getInitializer() != null;
092 }
093
094 @Override
095 public ItemPresentation getPresentation() {
096 return ItemPresentationProviders.getItemPresentation(this);
097 }
098
099 @Override
100 @Nullable
101 public JetParameterList getValueParameterList() {
102 return getStubOrPsiChild(JetStubElementTypes.VALUE_PARAMETER_LIST);
103 }
104
105 @Override
106 @NotNull
107 public List<JetParameter> getValueParameters() {
108 JetParameterList list = getValueParameterList();
109 return list != null ? list.getParameters() : Collections.<JetParameter>emptyList();
110 }
111
112 @Override
113 @Nullable
114 public JetExpression getBodyExpression() {
115 return findChildByClass(JetExpression.class);
116 }
117
118 @Override
119 public boolean hasBody() {
120 PsiJetFunctionStub stub = getStub();
121 if (stub != null) {
122 return stub.hasBody();
123 }
124 return getBodyExpression() != null;
125 }
126
127 @Override
128 public boolean hasDeclaredReturnType() {
129 return getTypeReference() != null;
130 }
131
132 @Override
133 @Nullable
134 public JetTypeReference getReceiverTypeReference() {
135 PsiJetFunctionStub stub = getStub();
136 if (stub != null) {
137 if (!stub.isExtension()) {
138 return null;
139 }
140 List<JetTypeReference> childTypeReferences = getStubOrPsiChildrenAsList(JetStubElementTypes.TYPE_REFERENCE);
141 if (!childTypeReferences.isEmpty()) {
142 return childTypeReferences.get(0);
143 }
144 else {
145 return null;
146 }
147 }
148 return getReceiverTypeRefByTree();
149 }
150
151 @Nullable
152 private JetTypeReference getReceiverTypeRefByTree() {
153 PsiElement child = getFirstChild();
154 while (child != null) {
155 IElementType tt = child.getNode().getElementType();
156 if (tt == JetTokens.LPAR || tt == JetTokens.COLON) break;
157 if (child instanceof JetTypeReference) {
158 return (JetTypeReference) child;
159 }
160 child = child.getNextSibling();
161 }
162
163 return null;
164 }
165
166 @Override
167 @Nullable
168 public JetTypeReference getTypeReference() {
169 PsiJetFunctionStub stub = getStub();
170 if (stub != null) {
171 List<JetTypeReference> typeReferences = getStubOrPsiChildrenAsList(JetStubElementTypes.TYPE_REFERENCE);
172 int returnTypeIndex = stub.isExtension() ? 1 : 0;
173 if (returnTypeIndex >= typeReferences.size()) {
174 return null;
175 }
176 return typeReferences.get(returnTypeIndex);
177 }
178 return TypeRefHelpersPackage.getTypeReference(this);
179 }
180
181 @Override
182 @Nullable
183 public JetTypeReference setTypeReference(@Nullable JetTypeReference typeRef) {
184 return TypeRefHelpersPackage.setTypeReference(this, getValueParameterList(), typeRef);
185 }
186
187 @Override
188 public boolean isLocal() {
189 PsiElement parent = getParent();
190 return !(parent instanceof JetFile || parent instanceof JetClassBody);
191 }
192 }