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 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        @Override
186        public ItemPresentation getPresentation() {
187            return ItemPresentationProviders.getItemPresentation(this);
188        }
189    }