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.load.java.structure.impl;
018
019 import com.intellij.psi.PsiAnnotation;
020 import com.intellij.psi.PsiClass;
021 import com.intellij.psi.PsiElement;
022 import com.intellij.psi.PsiJavaCodeReferenceElement;
023 import org.jetbrains.annotations.NotNull;
024 import org.jetbrains.annotations.Nullable;
025 import org.jetbrains.kotlin.load.java.structure.JavaAnnotation;
026 import org.jetbrains.kotlin.load.java.structure.JavaAnnotationArgument;
027 import org.jetbrains.kotlin.load.java.structure.JavaClass;
028 import org.jetbrains.kotlin.name.ClassId;
029 import org.jetbrains.kotlin.name.FqName;
030 import org.jetbrains.kotlin.name.Name;
031
032 import java.util.Collection;
033
034 import static org.jetbrains.kotlin.load.java.structure.impl.JavaElementCollectionFromPsiArrayUtil.namedAnnotationArguments;
035
036 public class JavaAnnotationImpl extends JavaElementImpl<PsiAnnotation> implements JavaAnnotation {
037 public JavaAnnotationImpl(@NotNull PsiAnnotation psiAnnotation) {
038 super(psiAnnotation);
039 }
040
041 @Override
042 @NotNull
043 public Collection<JavaAnnotationArgument> getArguments() {
044 return namedAnnotationArguments(getPsi().getParameterList().getAttributes());
045 }
046
047 @Override
048 @Nullable
049 public ClassId getClassId() {
050 PsiClass resolved = resolvePsi();
051 if (resolved != null) return computeClassId(resolved);
052
053 // External annotations do not have PSI behind them,
054 // so we can only heuristically reconstruct annotation class ids from qualified names
055 String qualifiedName = getPsi().getQualifiedName();
056 if (qualifiedName != null) return ClassId.topLevel(new FqName(qualifiedName));
057
058 return null;
059 }
060
061 @Nullable
062 @Override
063 public JavaClass resolve() {
064 PsiClass resolved = resolvePsi();
065 return resolved == null ? null : new JavaClassImpl(resolved);
066 }
067
068 @Nullable
069 private static ClassId computeClassId(@NotNull PsiClass psiClass) {
070 PsiClass container = psiClass.getContainingClass();
071 if (container != null) {
072 ClassId parentClassId = computeClassId(container);
073 String name = psiClass.getName();
074 return parentClassId == null || name == null ? null : parentClassId.createNestedClassId(Name.identifier(name));
075 }
076
077 String fqName = psiClass.getQualifiedName();
078 return fqName == null ? null : ClassId.topLevel(new FqName(fqName));
079 }
080
081 @Nullable
082 private PsiClass resolvePsi() {
083 PsiJavaCodeReferenceElement referenceElement = getPsi().getNameReferenceElement();
084 if (referenceElement == null) return null;
085
086 PsiElement resolved = referenceElement.resolve();
087 return resolved instanceof PsiClass ? (PsiClass) resolved : null;
088 }
089 }