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.psi.PsiElement;
021    import com.intellij.psi.stubs.IStubElementType;
022    import com.intellij.util.IncorrectOperationException;
023    import org.jetbrains.annotations.NonNls;
024    import org.jetbrains.annotations.NotNull;
025    import org.jetbrains.annotations.Nullable;
026    import org.jetbrains.jet.JetNodeTypes;
027    import org.jetbrains.jet.lang.psi.stubs.PsiJetObjectStub;
028    import org.jetbrains.jet.lang.psi.stubs.elements.JetStubElementTypes;
029    import org.jetbrains.jet.lang.resolve.name.FqName;
030    import org.jetbrains.jet.lexer.JetToken;
031    import org.jetbrains.jet.lexer.JetTokens;
032    
033    import java.util.Collections;
034    import java.util.List;
035    
036    public class JetObjectDeclaration extends JetNamedDeclarationStub<PsiJetObjectStub> implements JetClassOrObject  {
037        public JetObjectDeclaration(@NotNull ASTNode node) {
038            super(node);
039        }
040    
041        public JetObjectDeclaration(@NotNull PsiJetObjectStub stub) {
042            super(stub, JetStubElementTypes.OBJECT_DECLARATION);
043        }
044    
045        @NotNull
046        @Override
047        public IStubElementType getElementType() {
048            return JetStubElementTypes.OBJECT_DECLARATION;
049        }
050    
051        @Override
052        public String getName() {
053            PsiJetObjectStub stub = getStub();
054            if (stub != null) {
055                return stub.getName();
056            }
057    
058            JetObjectDeclarationName nameAsDeclaration = getNameAsDeclaration();
059            return nameAsDeclaration == null ? null : nameAsDeclaration.getName();
060        }
061    
062        /**
063         * Could be null for anonymous objects and object declared inside functions
064         * @return
065         */
066        public FqName getFqName() {
067            PsiJetObjectStub stub = getStub();
068            if (stub != null) {
069                return stub.getFqName();
070            }
071    
072            return JetPsiUtil.getFQName(this);
073        }
074    
075        public boolean isTopLevel() {
076            PsiJetObjectStub stub = getStub();
077            if (stub != null) {
078                return stub.isTopLevel();
079            }
080    
081            return getParent() instanceof JetFile;
082        }
083    
084        @Override
085        public PsiElement getNameIdentifier() {
086            JetObjectDeclarationName nameAsDeclaration = getNameAsDeclaration();
087            return nameAsDeclaration == null ? null : nameAsDeclaration.getNameIdentifier();
088        }
089    
090        @Override
091        public PsiElement setName(@NonNls @NotNull String name) throws IncorrectOperationException {
092            JetObjectDeclarationName nameAsDeclaration = getNameAsDeclaration();
093            return nameAsDeclaration == null ? null : nameAsDeclaration.setName(name);
094        }
095    
096        @Override
097        @Nullable
098        public JetObjectDeclarationName getNameAsDeclaration() {
099            return (JetObjectDeclarationName) findChildByType(JetNodeTypes.OBJECT_DECLARATION_NAME);
100        }
101    
102        @Override
103        @Nullable
104        public JetModifierList getModifierList() {
105            PsiElement parent = getParent();
106            if (isClassObject(parent)) {
107                assert parent instanceof JetDeclaration;
108                return ((JetDeclaration)parent).getModifierList();
109            }
110            return (JetModifierList) findChildByType(JetNodeTypes.MODIFIER_LIST);
111        }
112    
113    
114        private static boolean isClassObject(@NotNull PsiElement parent) {
115            return parent.getNode().getElementType().equals(JetNodeTypes.CLASS_OBJECT);
116        }
117    
118        @Override
119        public boolean hasModifier(JetToken modifier) {
120            JetModifierList modifierList = getModifierList();
121            return modifierList != null && modifierList.hasModifier(modifier);
122        }
123    
124        @Override
125        @Nullable
126        public JetDelegationSpecifierList getDelegationSpecifierList() {
127            return (JetDelegationSpecifierList) findChildByType(JetNodeTypes.DELEGATION_SPECIFIER_LIST);
128        }
129    
130        @Override
131        @NotNull
132        public List<JetDelegationSpecifier> getDelegationSpecifiers() {
133            JetDelegationSpecifierList list = getDelegationSpecifierList();
134            return list != null ? list.getDelegationSpecifiers() : Collections.<JetDelegationSpecifier>emptyList();
135        }
136    
137        @Override
138        @NotNull
139        public List<JetClassInitializer> getAnonymousInitializers() {
140            JetClassBody body = (JetClassBody) findChildByType(JetNodeTypes.CLASS_BODY);
141            if (body == null) return Collections.emptyList();
142    
143            return body.getAnonymousInitializers();
144        }
145    
146        @Override
147        public boolean hasPrimaryConstructor() {
148            return true;
149        }
150    
151        @Override
152        public JetClassBody getBody() {
153            return (JetClassBody) findChildByType(JetNodeTypes.CLASS_BODY);
154        }
155    
156        @Override
157        @NotNull
158        public List<JetDeclaration> getDeclarations() {
159            JetClassBody body = getBody();
160            if (body == null) return Collections.emptyList();
161    
162            return body.getDeclarations();
163        }
164    
165        @Override
166        public void accept(@NotNull JetVisitorVoid visitor) {
167            visitor.visitObjectDeclaration(this);
168        }
169    
170        @Override
171        public <R, D> R accept(@NotNull JetVisitor<R, D> visitor, D data) {
172            return visitor.visitObjectDeclaration(this, data);
173        }
174    
175        public boolean isObjectLiteral() {
176            return getParent() instanceof JetObjectLiteralExpression;
177        }
178    
179        @NotNull
180        public PsiElement getObjectKeyword() {
181            return findChildByType(JetTokens.OBJECT_KEYWORD);
182        }
183    
184        @Override
185        public void delete() throws IncorrectOperationException {
186            JetPsiUtil.deleteClass(this);
187        }
188    
189        //@Override
190        //public ItemPresentation getPresentation() {
191        //    return ItemPresentationProviders.getItemPresentation(this);
192        //}
193    }