LazyAnnotations implementation

This commit is contained in:
Andrey Breslav
2014-03-21 16:19:06 +04:00
parent 72b2fa77f7
commit bb17adc8d7
5 changed files with 175 additions and 52 deletions
@@ -126,7 +126,7 @@ public class AnnotationResolver {
}
@NotNull
public JetType resolveAnnotationType(
private JetType resolveAnnotationType(
JetScope scope,
JetAnnotationEntry entryElement,
BindingTrace trace
@@ -230,7 +230,7 @@ public class AnnotationResolver {
}
@Nullable
private static CompileTimeConstant<?> getAnnotationArgumentValue(
public static CompileTimeConstant<?> getAnnotationArgumentValue(
BindingTrace trace,
ValueParameterDescriptor parameterDescriptor,
ResolvedValueArgument resolvedArgument
@@ -21,6 +21,7 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.CallableDescriptor;
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
import org.jetbrains.jet.lang.descriptors.annotations.Annotations;
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
import org.jetbrains.jet.lang.types.JetType;
@@ -65,6 +66,9 @@ public class ForceResolveUtil {
public static void forceResolveAllContents(@NotNull Annotations annotations) {
doForceResolveAllContents(annotations);
for (AnnotationDescriptor annotation : annotations) {
doForceResolveAllContents(annotation);
}
}
private static void doForceResolveAllContents(Object object) {
@@ -0,0 +1,131 @@
/*
* Copyright 2010-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.lang.resolve.lazy.descriptors
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor
import org.jetbrains.jet.lang.resolve.name.FqName
import org.jetbrains.jet.lang.descriptors.annotations.Annotations
import org.jetbrains.jet.lang.resolve.lazy.LazyEntity
import org.jetbrains.jet.lang.psi.JetAnnotated
import org.jetbrains.jet.lang.psi.JetAnnotationEntry
import org.jetbrains.jet.lang.resolve.DescriptorUtils
import org.jetbrains.jet.lang.resolve.AnnotationResolver
import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor
import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant
import org.jetbrains.jet.lang.resolve.lazy.ForceResolveUtil
import org.jetbrains.jet.storage.StorageManager
import org.jetbrains.jet.lang.resolve.scopes.JetScope
import org.jetbrains.jet.lang.resolve.BindingTrace
import org.jetbrains.jet.utils.keysToMapExceptNulls
class LazyAnnotationsContext(
val annotationResolver: AnnotationResolver,
val storageManager: StorageManager,
val scope: JetScope,
val trace: BindingTrace
)
public class LazyAnnotations(
val c: LazyAnnotationsContext,
val annotatedElement: JetAnnotated
) : Annotations, LazyEntity {
override fun isEmpty() = annotatedElement.getAnnotationEntries().isEmpty()
val _annotation = c.storageManager.createMemoizedFunction {
(entry: JetAnnotationEntry) ->
LazyAnnotationDescriptor(c, entry)
}
override fun findAnnotation(fqName: FqName): AnnotationDescriptor? {
// We can not efficiently check short names here:
// an annotation class may be renamed on import
for (annotationDescriptor in iterator()) {
val annotationType = annotationDescriptor.getType()
if (annotationType.isError()) continue
val descriptor = annotationType.getConstructor().getDeclarationDescriptor()
if (descriptor == null) continue
if (DescriptorUtils.getFqNameSafe(descriptor) == fqName) {
return annotationDescriptor
}
}
return null
}
override fun iterator(): Iterator<AnnotationDescriptor> {
return annotatedElement.getAnnotationEntries().stream().map(_annotation).iterator()
}
override fun forceResolveAllContents() {
// To resolve all entries
this.toList()
}
}
public class LazyAnnotationDescriptor(
val c: LazyAnnotationsContext,
val annotationEntry: JetAnnotationEntry
) : AnnotationDescriptor, LazyEntity {
private val _resolutionResults = c.storageManager.createLazyValue {
val results = c.annotationResolver.resolveAnnotationCall(
annotationEntry,
c.scope,
c.trace
)
AnnotationResolver.checkAnnotationType(annotationEntry, c.trace, results)
results
}
private val _type = c.storageManager.createLazyValue {
c.annotationResolver.resolveAnnotationType(
c.scope,
annotationEntry
)
}
override fun getType() = _type()
private val _valueArguments = c.storageManager.createMemoizedFunctionWithNullableValues @f {
(valueParameterDescriptor: ValueParameterDescriptor): CompileTimeConstant<*>? ->
if (!_resolutionResults().isSingleResult()) return@f null
val resolvedValueArgument = _resolutionResults().getResultingCall().getValueArguments()[valueParameterDescriptor]
if (resolvedValueArgument == null) return@f null
AnnotationResolver.getAnnotationArgumentValue(c.trace, valueParameterDescriptor, resolvedValueArgument)
}
override fun getValueArgument(valueParameterDescriptor: ValueParameterDescriptor): CompileTimeConstant<out Any?>? {
return _valueArguments(valueParameterDescriptor)
}
override fun getAllValueArguments(): Map<ValueParameterDescriptor, CompileTimeConstant<out Any?>> {
if (!_resolutionResults().isSingleResult()) return mapOf()
return _resolutionResults().getResultingCall().getValueArguments().keySet().keysToMapExceptNulls {
getValueArgument(it)
}
}
override fun forceResolveAllContents() {
ForceResolveUtil.forceResolveAllContents(getType())
getAllValueArguments()
}
}
@@ -1,50 +0,0 @@
/*
* Copyright 2010-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.lang.descriptors.annotations;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.resolve.name.FqName;
import java.util.Collections;
import java.util.Iterator;
public interface Annotations extends Iterable<AnnotationDescriptor> {
Annotations EMPTY = new Annotations() {
@Override
public boolean isEmpty() {
return true;
}
@Nullable
@Override
public AnnotationDescriptor findAnnotation(@NotNull FqName fqName) {
return null;
}
@NotNull
@Override
public Iterator<AnnotationDescriptor> iterator() {
return Collections.<AnnotationDescriptor>emptyList().iterator();
}
};
boolean isEmpty();
@Nullable
AnnotationDescriptor findAnnotation(@NotNull FqName fqName);
}
@@ -0,0 +1,38 @@
/*
* Copyright 2010-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.lang.descriptors.annotations
import org.jetbrains.annotations.Nullable
import org.jetbrains.jet.lang.resolve.name.FqName
import java.util.Collections
public trait Annotations : Iterable<AnnotationDescriptor> {
fun isEmpty(): Boolean
fun findAnnotation(fqName: FqName): AnnotationDescriptor?
class object {
val EMPTY: Annotations = object : Annotations {
override fun isEmpty() = true
override fun findAnnotation(fqName: FqName) = null
override fun iterator() = Collections.emptyList<AnnotationDescriptor>().iterator()
}
}
}