001 /* 002 * Copyright 2010-2015 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.kotlin.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.util.IncorrectOperationException; 024 import org.jetbrains.annotations.NonNls; 025 import org.jetbrains.annotations.NotNull; 026 import org.jetbrains.annotations.Nullable; 027 import org.jetbrains.kotlin.JetNodeTypes; 028 import org.jetbrains.kotlin.lexer.JetModifierKeywordToken; 029 import org.jetbrains.kotlin.lexer.JetTokens; 030 import org.jetbrains.kotlin.name.SpecialNames; 031 import org.jetbrains.kotlin.psi.stubs.KotlinObjectStub; 032 import org.jetbrains.kotlin.psi.stubs.elements.JetStubElementTypes; 033 034 import java.util.Collections; 035 import java.util.List; 036 037 public class JetObjectDeclaration extends JetNamedDeclarationStub<KotlinObjectStub> implements JetClassOrObject { 038 public JetObjectDeclaration(@NotNull ASTNode node) { 039 super(node); 040 } 041 042 public JetObjectDeclaration(@NotNull KotlinObjectStub stub) { 043 super(stub, JetStubElementTypes.OBJECT_DECLARATION); 044 } 045 046 @Override 047 public String getName() { 048 KotlinObjectStub stub = getStub(); 049 if (stub != null) { 050 return stub.getName(); 051 } 052 053 JetObjectDeclarationName nameAsDeclaration = getNameAsDeclaration(); 054 if (nameAsDeclaration == null && isCompanion()) { 055 //NOTE: a hack in PSI that simplifies writing frontend code 056 return SpecialNames.DEFAULT_NAME_FOR_COMPANION_OBJECT.toString(); 057 } 058 return nameAsDeclaration == null ? null : nameAsDeclaration.getName(); 059 } 060 061 @Override 062 public boolean isTopLevel() { 063 KotlinObjectStub stub = getStub(); 064 if (stub != null) { 065 return stub.isTopLevel(); 066 } 067 068 return getParent() instanceof JetFile; 069 } 070 071 @Override 072 public PsiElement getNameIdentifier() { 073 JetObjectDeclarationName nameAsDeclaration = getNameAsDeclaration(); 074 return nameAsDeclaration == null ? null : nameAsDeclaration.getNameIdentifier(); 075 } 076 077 @Override 078 public PsiElement setName(@NonNls @NotNull String name) throws IncorrectOperationException { 079 JetObjectDeclarationName declarationName = getNameAsDeclaration(); 080 if (declarationName == null) { 081 JetPsiFactory psiFactory = new JetPsiFactory(getProject()); 082 PsiElement result = addAfter(psiFactory.createObjectDeclarationName(name), getObjectKeyword()); 083 addAfter(psiFactory.createWhiteSpace(), getObjectKeyword()); 084 085 return result; 086 } else { 087 return declarationName.setName(name); 088 } 089 } 090 091 @Override 092 @Nullable 093 public JetObjectDeclarationName getNameAsDeclaration() { 094 return (JetObjectDeclarationName) findChildByType(JetNodeTypes.OBJECT_DECLARATION_NAME); 095 } 096 097 public boolean isCompanion() { 098 KotlinObjectStub stub = getStub(); 099 if (stub != null) { 100 return stub.isCompanion(); 101 } 102 return getClassKeyword() != null || hasModifier(JetTokens.COMPANION_KEYWORD); 103 } 104 105 @Override 106 public boolean hasModifier(@NotNull JetModifierKeywordToken modifier) { 107 JetModifierList modifierList = getModifierList(); 108 return modifierList != null && modifierList.hasModifier(modifier); 109 } 110 111 @Override 112 @Nullable 113 public JetDelegationSpecifierList getDelegationSpecifierList() { 114 return getStubOrPsiChild(JetStubElementTypes.DELEGATION_SPECIFIER_LIST); 115 } 116 117 @Override 118 @NotNull 119 public List<JetDelegationSpecifier> getDelegationSpecifiers() { 120 JetDelegationSpecifierList list = getDelegationSpecifierList(); 121 return list != null ? list.getDelegationSpecifiers() : Collections.<JetDelegationSpecifier>emptyList(); 122 } 123 124 @Override 125 @NotNull 126 public List<JetClassInitializer> getAnonymousInitializers() { 127 JetClassBody body = getBody(); 128 if (body == null) return Collections.emptyList(); 129 130 return body.getAnonymousInitializers(); 131 } 132 133 @Override 134 public JetClassBody getBody() { 135 return getStubOrPsiChild(JetStubElementTypes.CLASS_BODY); 136 } 137 138 @Override 139 public boolean isLocal() { 140 KotlinObjectStub stub = getStub(); 141 if (stub != null) { 142 return stub.isLocal(); 143 } 144 return JetPsiUtil.isLocal(this); 145 } 146 147 @Override 148 public int getTextOffset() { 149 PsiElement nameIdentifier = getNameIdentifier(); 150 if (nameIdentifier != null) { 151 return nameIdentifier.getTextRange().getStartOffset(); 152 } 153 else { 154 return getObjectKeyword().getTextRange().getStartOffset(); 155 } 156 } 157 158 @Override 159 @NotNull 160 public List<JetDeclaration> getDeclarations() { 161 JetClassBody body = getBody(); 162 if (body == null) return Collections.emptyList(); 163 164 return body.getDeclarations(); 165 } 166 167 @Override 168 public <R, D> R accept(@NotNull JetVisitor<R, D> visitor, D data) { 169 return visitor.visitObjectDeclaration(this, data); 170 } 171 172 public boolean isObjectLiteral() { 173 KotlinObjectStub stub = getStub(); 174 if (stub != null) { 175 return stub.isObjectLiteral(); 176 } 177 return getParent() instanceof JetObjectLiteralExpression; 178 } 179 180 @NotNull 181 public PsiElement getObjectKeyword() { 182 return findChildByType(JetTokens.OBJECT_KEYWORD); 183 } 184 185 @Nullable 186 public PsiElement getClassKeyword() { 187 return findChildByType(JetTokens.CLASS_KEYWORD); 188 } 189 190 @Override 191 public void delete() throws IncorrectOperationException { 192 JetPsiUtil.deleteClass(this); 193 } 194 195 @Override 196 public ItemPresentation getPresentation() { 197 return ItemPresentationProviders.getItemPresentation(this); 198 } 199 }