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 && isDefault()) {
055               //NOTE: a hack in PSI that simplifies writing frontend code
056                return SpecialNames.DEFAULT_NAME_FOR_DEFAULT_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 nameAsDeclaration = getNameAsDeclaration();
080            return nameAsDeclaration == null ? null : nameAsDeclaration.setName(name);
081        }
082    
083        @Override
084        @Nullable
085        public JetObjectDeclarationName getNameAsDeclaration() {
086            return (JetObjectDeclarationName) findChildByType(JetNodeTypes.OBJECT_DECLARATION_NAME);
087        }
088    
089        public boolean isDefault() {
090            KotlinObjectStub stub = getStub();
091            if (stub != null) {
092                return stub.isDefault();
093            }
094            return getClassKeyword() != null || hasModifier(JetTokens.DEFAULT_KEYWORD);
095        }
096    
097        @Override
098        public boolean hasModifier(@NotNull JetModifierKeywordToken modifier) {
099            JetModifierList modifierList = getModifierList();
100            return modifierList != null && modifierList.hasModifier(modifier);
101        }
102    
103        @Override
104        @Nullable
105        public JetDelegationSpecifierList getDelegationSpecifierList() {
106            return getStubOrPsiChild(JetStubElementTypes.DELEGATION_SPECIFIER_LIST);
107        }
108    
109        @Override
110        @NotNull
111        public List<JetDelegationSpecifier> getDelegationSpecifiers() {
112            JetDelegationSpecifierList list = getDelegationSpecifierList();
113            return list != null ? list.getDelegationSpecifiers() : Collections.<JetDelegationSpecifier>emptyList();
114        }
115    
116        @Override
117        @NotNull
118        public List<JetClassInitializer> getAnonymousInitializers() {
119            JetClassBody body = getBody();
120            if (body == null) return Collections.emptyList();
121    
122            return body.getAnonymousInitializers();
123        }
124    
125        @Override
126        public boolean hasPrimaryConstructor() {
127            return true;
128        }
129    
130        @Override
131        public JetClassBody getBody() {
132            return getStubOrPsiChild(JetStubElementTypes.CLASS_BODY);
133        }
134    
135        @Override
136        public boolean isLocal() {
137            KotlinObjectStub stub = getStub();
138            if (stub != null) {
139                return stub.isLocal();
140            }
141            return JetPsiUtil.isLocal(this);
142        }
143    
144        @Override
145        public int getTextOffset() {
146            PsiElement nameIdentifier = getNameIdentifier();
147            if (nameIdentifier != null) {
148                return nameIdentifier.getTextRange().getStartOffset();
149            }
150            else {
151                return getObjectKeyword().getTextRange().getStartOffset();
152            }
153        }
154    
155        @Override
156        @NotNull
157        public List<JetDeclaration> getDeclarations() {
158            JetClassBody body = getBody();
159            if (body == null) return Collections.emptyList();
160    
161            return body.getDeclarations();
162        }
163    
164        @Override
165        public <R, D> R accept(@NotNull JetVisitor<R, D> visitor, D data) {
166            return visitor.visitObjectDeclaration(this, data);
167        }
168    
169        public boolean isObjectLiteral() {
170            KotlinObjectStub stub = getStub();
171            if (stub != null) {
172                return stub.isObjectLiteral();
173            }
174            return getParent() instanceof JetObjectLiteralExpression;
175        }
176    
177        @NotNull
178        public PsiElement getObjectKeyword() {
179            return findChildByType(JetTokens.OBJECT_KEYWORD);
180        }
181    
182        @Nullable
183        public PsiElement getClassKeyword() {
184            return findChildByType(JetTokens.CLASS_KEYWORD);
185        }
186    
187        @Override
188        public void delete() throws IncorrectOperationException {
189            JetPsiUtil.deleteClass(this);
190        }
191    
192        @Override
193        public ItemPresentation getPresentation() {
194            return ItemPresentationProviders.getItemPresentation(this);
195        }
196    }