8303820: Simplify type metadata
Reviewed-by: vromero
This commit is contained in:
parent
75d630621c
commit
b9951dd639
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1999, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -30,12 +30,14 @@ import java.util.ArrayDeque;
|
||||
import java.util.Collections;
|
||||
import java.util.EnumMap;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import javax.lang.model.type.*;
|
||||
|
||||
import com.sun.tools.javac.code.Symbol.*;
|
||||
import com.sun.tools.javac.code.TypeMetadata.Entry;
|
||||
import com.sun.tools.javac.code.TypeMetadata.Annotations;
|
||||
import com.sun.tools.javac.code.TypeMetadata.ConstantValue;
|
||||
import com.sun.tools.javac.code.Types.TypeMapping;
|
||||
import com.sun.tools.javac.code.Types.UniqueType;
|
||||
import com.sun.tools.javac.comp.Infer.IncorporationAction;
|
||||
@ -86,15 +88,7 @@ public abstract class Type extends AnnoConstruct implements TypeMirror, PoolCons
|
||||
* class, a given {@code Type} may have at most one metadata array
|
||||
* entry of that class.
|
||||
*/
|
||||
protected final TypeMetadata metadata;
|
||||
|
||||
public TypeMetadata getMetadata() {
|
||||
return metadata;
|
||||
}
|
||||
|
||||
public Entry getMetadataOfKind(final Entry.Kind kind) {
|
||||
return metadata != null ? metadata.get(kind) : null;
|
||||
}
|
||||
protected final List<TypeMetadata> metadata;
|
||||
|
||||
/** Constant type: no type at all. */
|
||||
public static final JCNoType noType = new JCNoType() {
|
||||
@ -188,7 +182,8 @@ public abstract class Type extends AnnoConstruct implements TypeMirror, PoolCons
|
||||
* @return the constant value attribute of this type
|
||||
*/
|
||||
public Object constValue() {
|
||||
return null;
|
||||
return getMetadata(TypeMetadata.ConstantValue.class)
|
||||
.map(ConstantValue::value).orElse(null);
|
||||
}
|
||||
|
||||
/** Is this a constant type whose value is false?
|
||||
@ -230,7 +225,7 @@ public abstract class Type extends AnnoConstruct implements TypeMirror, PoolCons
|
||||
/** Define a type given its tag, type symbol, and type annotations
|
||||
*/
|
||||
|
||||
public Type(TypeSymbol tsym, TypeMetadata metadata) {
|
||||
public Type(TypeSymbol tsym, List<TypeMetadata> metadata) {
|
||||
Assert.checkNonNull(metadata);
|
||||
this.tsym = tsym;
|
||||
this.metadata = metadata;
|
||||
@ -345,13 +340,53 @@ public abstract class Type extends AnnoConstruct implements TypeMirror, PoolCons
|
||||
* it should not be used outside this class.
|
||||
*/
|
||||
protected Type typeNoMetadata() {
|
||||
return metadata == TypeMetadata.EMPTY ? this : baseType();
|
||||
return metadata.isEmpty() ? this : baseType();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new copy of this type but with the specified TypeMetadata.
|
||||
* Only to be used internally!
|
||||
*/
|
||||
public abstract Type cloneWithMetadata(TypeMetadata metadata);
|
||||
protected Type cloneWithMetadata(List<TypeMetadata> metadata) {
|
||||
throw new AssertionError("Cannot add metadata to this type: " + getTag());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all the type metadata associated with this type.
|
||||
*/
|
||||
public List<TypeMetadata> getMetadata() {
|
||||
return metadata;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the type metadata of the given kind associated with this type (if any).
|
||||
*/
|
||||
public <M extends TypeMetadata> Optional<M> getMetadata(Class<M> metadataClass) {
|
||||
return metadata.stream()
|
||||
.filter(m -> metadataClass.isAssignableFrom(m.getClass()))
|
||||
.map(metadataClass::cast)
|
||||
.findFirst();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new copy of this type but with the specified type metadata.
|
||||
* If this type is already associated with a type metadata of the same class,
|
||||
* an exception is thrown.
|
||||
*/
|
||||
public Type addMetadata(TypeMetadata md) {
|
||||
Assert.check(getMetadata(md.getClass()).isEmpty());
|
||||
return cloneWithMetadata(metadata.append(md));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new copy of this type but without the specified type metadata.
|
||||
*/
|
||||
public Type dropMetadata(Class<? extends TypeMetadata> metadataClass) {
|
||||
List<TypeMetadata> newMetadata = metadata.stream()
|
||||
.filter(m -> !metadataClass.isAssignableFrom(m.getClass()))
|
||||
.collect(List.collector());
|
||||
return cloneWithMetadata(newMetadata);
|
||||
}
|
||||
|
||||
/**
|
||||
* Does this type require annotation stripping for API clients?
|
||||
@ -398,24 +433,22 @@ public abstract class Type extends AnnoConstruct implements TypeMirror, PoolCons
|
||||
}
|
||||
};
|
||||
|
||||
public Type preannotatedType() {
|
||||
return addMetadata(new Annotations());
|
||||
}
|
||||
|
||||
public Type annotatedType(final List<Attribute.TypeCompound> annos) {
|
||||
final Entry annoMetadata = new TypeMetadata.Annotations(annos);
|
||||
return cloneWithMetadata(metadata.combine(annoMetadata));
|
||||
return addMetadata(new Annotations(annos));
|
||||
}
|
||||
|
||||
public boolean isAnnotated() {
|
||||
final TypeMetadata.Annotations metadata =
|
||||
(TypeMetadata.Annotations)getMetadataOfKind(Entry.Kind.ANNOTATIONS);
|
||||
|
||||
return null != metadata && !metadata.getAnnotations().isEmpty();
|
||||
return getMetadata(TypeMetadata.Annotations.class).isPresent();
|
||||
}
|
||||
|
||||
@Override @DefinedBy(Api.LANGUAGE_MODEL)
|
||||
public List<Attribute.TypeCompound> getAnnotationMirrors() {
|
||||
final TypeMetadata.Annotations metadata =
|
||||
(TypeMetadata.Annotations)getMetadataOfKind(Entry.Kind.ANNOTATIONS);
|
||||
|
||||
return metadata == null ? List.nil() : metadata.getAnnotations();
|
||||
return getMetadata(TypeMetadata.Annotations.class)
|
||||
.map(Annotations::annotations).orElse(List.nil());
|
||||
}
|
||||
|
||||
|
||||
@ -688,17 +721,17 @@ public abstract class Type extends AnnoConstruct implements TypeMirror, PoolCons
|
||||
TypeTag tag;
|
||||
|
||||
public JCPrimitiveType(TypeTag tag, TypeSymbol tsym) {
|
||||
this(tag, tsym, TypeMetadata.EMPTY);
|
||||
this(tag, tsym, List.nil());
|
||||
}
|
||||
|
||||
private JCPrimitiveType(TypeTag tag, TypeSymbol tsym, TypeMetadata metadata) {
|
||||
private JCPrimitiveType(TypeTag tag, TypeSymbol tsym, List<TypeMetadata> metadata) {
|
||||
super(tsym, metadata);
|
||||
this.tag = tag;
|
||||
Assert.check(tag.isPrimitive);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JCPrimitiveType cloneWithMetadata(TypeMetadata md) {
|
||||
protected JCPrimitiveType cloneWithMetadata(List<TypeMetadata> md) {
|
||||
return new JCPrimitiveType(tag, tsym, md) {
|
||||
@Override
|
||||
public Type baseType() { return JCPrimitiveType.this.baseType(); }
|
||||
@ -744,17 +777,7 @@ public abstract class Type extends AnnoConstruct implements TypeMirror, PoolCons
|
||||
*/
|
||||
@Override
|
||||
public Type constType(Object constValue) {
|
||||
final Object value = constValue;
|
||||
return new JCPrimitiveType(tag, tsym, metadata) {
|
||||
@Override
|
||||
public Object constValue() {
|
||||
return value;
|
||||
}
|
||||
@Override
|
||||
public Type baseType() {
|
||||
return tsym.type;
|
||||
}
|
||||
};
|
||||
return addMetadata(new ConstantValue(constValue));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -829,21 +852,21 @@ public abstract class Type extends AnnoConstruct implements TypeMirror, PoolCons
|
||||
}
|
||||
|
||||
public WildcardType(Type type, BoundKind kind, TypeSymbol tsym) {
|
||||
this(type, kind, tsym, null, TypeMetadata.EMPTY);
|
||||
this(type, kind, tsym, null, List.nil());
|
||||
}
|
||||
|
||||
public WildcardType(Type type, BoundKind kind, TypeSymbol tsym,
|
||||
TypeMetadata metadata) {
|
||||
List<TypeMetadata> metadata) {
|
||||
this(type, kind, tsym, null, metadata);
|
||||
}
|
||||
|
||||
public WildcardType(Type type, BoundKind kind, TypeSymbol tsym,
|
||||
TypeVar bound) {
|
||||
this(type, kind, tsym, bound, TypeMetadata.EMPTY);
|
||||
this(type, kind, tsym, bound, List.nil());
|
||||
}
|
||||
|
||||
public WildcardType(Type type, BoundKind kind, TypeSymbol tsym,
|
||||
TypeVar bound, TypeMetadata metadata) {
|
||||
TypeVar bound, List<TypeMetadata> metadata) {
|
||||
super(tsym, metadata);
|
||||
this.type = Assert.checkNonNull(type);
|
||||
this.kind = kind;
|
||||
@ -851,7 +874,7 @@ public abstract class Type extends AnnoConstruct implements TypeMirror, PoolCons
|
||||
}
|
||||
|
||||
@Override
|
||||
public WildcardType cloneWithMetadata(TypeMetadata md) {
|
||||
protected WildcardType cloneWithMetadata(List<TypeMetadata> md) {
|
||||
return new WildcardType(type, kind, tsym, bound, md) {
|
||||
@Override
|
||||
public Type baseType() { return WildcardType.this.baseType(); }
|
||||
@ -978,11 +1001,11 @@ public abstract class Type extends AnnoConstruct implements TypeMirror, PoolCons
|
||||
public List<Type> all_interfaces_field;
|
||||
|
||||
public ClassType(Type outer, List<Type> typarams, TypeSymbol tsym) {
|
||||
this(outer, typarams, tsym, TypeMetadata.EMPTY);
|
||||
this(outer, typarams, tsym, List.nil());
|
||||
}
|
||||
|
||||
public ClassType(Type outer, List<Type> typarams, TypeSymbol tsym,
|
||||
TypeMetadata metadata) {
|
||||
List<TypeMetadata> metadata) {
|
||||
super(tsym, metadata);
|
||||
this.outer_field = outer;
|
||||
this.typarams_field = typarams;
|
||||
@ -996,7 +1019,7 @@ public abstract class Type extends AnnoConstruct implements TypeMirror, PoolCons
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClassType cloneWithMetadata(TypeMetadata md) {
|
||||
protected ClassType cloneWithMetadata(List<TypeMetadata> md) {
|
||||
return new ClassType(outer_field, typarams_field, tsym, md) {
|
||||
@Override
|
||||
public Type baseType() { return ClassType.this.baseType(); }
|
||||
@ -1014,17 +1037,7 @@ public abstract class Type extends AnnoConstruct implements TypeMirror, PoolCons
|
||||
}
|
||||
|
||||
public Type constType(Object constValue) {
|
||||
final Object value = constValue;
|
||||
return new ClassType(getEnclosingType(), typarams_field, tsym, metadata) {
|
||||
@Override
|
||||
public Object constValue() {
|
||||
return value;
|
||||
}
|
||||
@Override
|
||||
public Type baseType() {
|
||||
return tsym.type;
|
||||
}
|
||||
};
|
||||
return addMetadata(new ConstantValue(constValue));
|
||||
}
|
||||
|
||||
/** The Java source which this type represents.
|
||||
@ -1190,7 +1203,7 @@ public abstract class Type extends AnnoConstruct implements TypeMirror, PoolCons
|
||||
|
||||
public static class ErasedClassType extends ClassType {
|
||||
public ErasedClassType(Type outer, TypeSymbol tsym,
|
||||
TypeMetadata metadata) {
|
||||
List<TypeMetadata> metadata) {
|
||||
super(outer, List.nil(), tsym, metadata);
|
||||
}
|
||||
|
||||
@ -1215,11 +1228,6 @@ public abstract class Type extends AnnoConstruct implements TypeMirror, PoolCons
|
||||
alternatives_field = alternatives;
|
||||
}
|
||||
|
||||
@Override
|
||||
public UnionClassType cloneWithMetadata(TypeMetadata md) {
|
||||
throw new AssertionError("Cannot add metadata to a union type");
|
||||
}
|
||||
|
||||
public Type getLub() {
|
||||
return tsym.type;
|
||||
}
|
||||
@ -1271,11 +1279,6 @@ public abstract class Type extends AnnoConstruct implements TypeMirror, PoolCons
|
||||
!supertype_field.isInterface(), supertype_field);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IntersectionClassType cloneWithMetadata(TypeMetadata md) {
|
||||
throw new AssertionError("Cannot add metadata to an intersection type");
|
||||
}
|
||||
|
||||
@DefinedBy(Api.LANGUAGE_MODEL)
|
||||
public java.util.List<? extends TypeMirror> getBounds() {
|
||||
return Collections.unmodifiableList(getExplicitComponents());
|
||||
@ -1318,11 +1321,11 @@ public abstract class Type extends AnnoConstruct implements TypeMirror, PoolCons
|
||||
public Type elemtype;
|
||||
|
||||
public ArrayType(Type elemtype, TypeSymbol arrayClass) {
|
||||
this(elemtype, arrayClass, TypeMetadata.EMPTY);
|
||||
this(elemtype, arrayClass, List.nil());
|
||||
}
|
||||
|
||||
public ArrayType(Type elemtype, TypeSymbol arrayClass,
|
||||
TypeMetadata metadata) {
|
||||
List<TypeMetadata> metadata) {
|
||||
super(arrayClass, metadata);
|
||||
this.elemtype = elemtype;
|
||||
}
|
||||
@ -1338,7 +1341,7 @@ public abstract class Type extends AnnoConstruct implements TypeMirror, PoolCons
|
||||
}
|
||||
|
||||
@Override
|
||||
public ArrayType cloneWithMetadata(TypeMetadata md) {
|
||||
protected ArrayType cloneWithMetadata(List<TypeMetadata> md) {
|
||||
return new ArrayType(elemtype, tsym, md) {
|
||||
@Override
|
||||
public Type baseType() { return ArrayType.this.baseType(); }
|
||||
@ -1463,17 +1466,12 @@ public abstract class Type extends AnnoConstruct implements TypeMirror, PoolCons
|
||||
TypeSymbol methodClass) {
|
||||
// Presently no way to refer to a method type directly, so
|
||||
// we cannot put type annotations on it.
|
||||
super(methodClass, TypeMetadata.EMPTY);
|
||||
super(methodClass, List.nil());
|
||||
this.argtypes = argtypes;
|
||||
this.restype = restype;
|
||||
this.thrown = thrown;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MethodType cloneWithMetadata(TypeMetadata md) {
|
||||
throw new AssertionError("Cannot add metadata to a method type");
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeTag getTag() {
|
||||
return METHOD;
|
||||
@ -1560,12 +1558,7 @@ public abstract class Type extends AnnoConstruct implements TypeMirror, PoolCons
|
||||
|
||||
PackageType(PackageSymbol tsym) {
|
||||
// Package types cannot be annotated
|
||||
super(tsym, TypeMetadata.EMPTY);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PackageType cloneWithMetadata(TypeMetadata md) {
|
||||
throw new AssertionError("Cannot add metadata to a package type");
|
||||
super(tsym, List.nil());
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -1598,12 +1591,7 @@ public abstract class Type extends AnnoConstruct implements TypeMirror, PoolCons
|
||||
|
||||
ModuleType(ModuleSymbol tsym) {
|
||||
// Module types cannot be annotated
|
||||
super(tsym, TypeMetadata.EMPTY);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ModuleType cloneWithMetadata(TypeMetadata md) {
|
||||
throw new AssertionError("Cannot add metadata to a module type");
|
||||
super(tsym, List.nil());
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -1659,7 +1647,7 @@ public abstract class Type extends AnnoConstruct implements TypeMirror, PoolCons
|
||||
public Type lower;
|
||||
|
||||
public TypeVar(Name name, Symbol owner, Type lower) {
|
||||
super(null, TypeMetadata.EMPTY);
|
||||
super(null, List.nil());
|
||||
Assert.checkNonNull(lower);
|
||||
tsym = new TypeVariableSymbol(0, name, this, owner);
|
||||
this.setUpperBound(null);
|
||||
@ -1667,11 +1655,11 @@ public abstract class Type extends AnnoConstruct implements TypeMirror, PoolCons
|
||||
}
|
||||
|
||||
public TypeVar(TypeSymbol tsym, Type bound, Type lower) {
|
||||
this(tsym, bound, lower, TypeMetadata.EMPTY);
|
||||
this(tsym, bound, lower, List.nil());
|
||||
}
|
||||
|
||||
public TypeVar(TypeSymbol tsym, Type bound, Type lower,
|
||||
TypeMetadata metadata) {
|
||||
List<TypeMetadata> metadata) {
|
||||
super(tsym, metadata);
|
||||
Assert.checkNonNull(lower);
|
||||
this.setUpperBound(bound);
|
||||
@ -1679,7 +1667,7 @@ public abstract class Type extends AnnoConstruct implements TypeMirror, PoolCons
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeVar cloneWithMetadata(TypeMetadata md) {
|
||||
protected TypeVar cloneWithMetadata(List<TypeMetadata> md) {
|
||||
return new TypeVar(tsym, getUpperBound(), lower, md) {
|
||||
@Override
|
||||
public Type baseType() { return TypeVar.this.baseType(); }
|
||||
@ -1762,13 +1750,13 @@ public abstract class Type extends AnnoConstruct implements TypeMirror, PoolCons
|
||||
Type upper,
|
||||
Type lower,
|
||||
WildcardType wildcard,
|
||||
TypeMetadata metadata) {
|
||||
List<TypeMetadata> metadata) {
|
||||
super(tsym, bound, lower, metadata);
|
||||
this.wildcard = wildcard;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CapturedType cloneWithMetadata(TypeMetadata md) {
|
||||
protected CapturedType cloneWithMetadata(List<TypeMetadata> md) {
|
||||
return new CapturedType(tsym, getUpperBound(), getUpperBound(), lower, wildcard, md) {
|
||||
@Override
|
||||
public Type baseType() { return CapturedType.this.baseType(); }
|
||||
@ -1807,11 +1795,11 @@ public abstract class Type extends AnnoConstruct implements TypeMirror, PoolCons
|
||||
public TypeTag tag;
|
||||
|
||||
public DelegatedType(TypeTag tag, Type qtype) {
|
||||
this(tag, qtype, TypeMetadata.EMPTY);
|
||||
this(tag, qtype, List.nil());
|
||||
}
|
||||
|
||||
public DelegatedType(TypeTag tag, Type qtype,
|
||||
TypeMetadata metadata) {
|
||||
List<TypeMetadata> metadata) {
|
||||
super(qtype.tsym, metadata);
|
||||
this.tag = tag;
|
||||
this.qtype = qtype;
|
||||
@ -1844,11 +1832,6 @@ public abstract class Type extends AnnoConstruct implements TypeMirror, PoolCons
|
||||
this.tvars = tvars;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ForAll cloneWithMetadata(TypeMetadata md) {
|
||||
throw new AssertionError("Cannot add metadata to a forall type");
|
||||
}
|
||||
|
||||
@Override
|
||||
public <R,S> R accept(Type.Visitor<R,S> v, S s) {
|
||||
return v.visitForAll(this, s);
|
||||
@ -2077,11 +2060,6 @@ public abstract class Type extends AnnoConstruct implements TypeMirror, PoolCons
|
||||
uv2.kind = kind;
|
||||
}
|
||||
|
||||
@Override
|
||||
public UndetVar cloneWithMetadata(TypeMetadata md) {
|
||||
throw new AssertionError("Cannot add metadata to an UndetVar type");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPartial() {
|
||||
return true;
|
||||
@ -2224,12 +2202,7 @@ public abstract class Type extends AnnoConstruct implements TypeMirror, PoolCons
|
||||
// Need to use List.nil(), because JCNoType constructor
|
||||
// gets called in static initializers in Type, where
|
||||
// noAnnotations is also defined.
|
||||
super(null, TypeMetadata.EMPTY);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JCNoType cloneWithMetadata(TypeMetadata md) {
|
||||
throw new AssertionError("Cannot add metadata to a JCNoType");
|
||||
super(null, List.nil());
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -2257,12 +2230,7 @@ public abstract class Type extends AnnoConstruct implements TypeMirror, PoolCons
|
||||
|
||||
public JCVoidType() {
|
||||
// Void cannot be annotated
|
||||
super(null, TypeMetadata.EMPTY);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JCVoidType cloneWithMetadata(TypeMetadata md) {
|
||||
throw new AssertionError("Cannot add metadata to a void type");
|
||||
super(null, List.nil());
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -2292,12 +2260,7 @@ public abstract class Type extends AnnoConstruct implements TypeMirror, PoolCons
|
||||
static class BottomType extends Type implements NullType {
|
||||
public BottomType() {
|
||||
// Bottom is a synthesized internal type, so it cannot be annotated
|
||||
super(null, TypeMetadata.EMPTY);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BottomType cloneWithMetadata(TypeMetadata md) {
|
||||
throw new AssertionError("Cannot add metadata to a bottom type");
|
||||
super(null, List.nil());
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -2354,14 +2317,14 @@ public abstract class Type extends AnnoConstruct implements TypeMirror, PoolCons
|
||||
}
|
||||
|
||||
private ErrorType(Type originalType, TypeSymbol tsym,
|
||||
TypeMetadata metadata) {
|
||||
List<TypeMetadata> metadata) {
|
||||
super(noType, List.nil(), null, metadata);
|
||||
this.tsym = tsym;
|
||||
this.originalType = (originalType == null ? noType : originalType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ErrorType cloneWithMetadata(TypeMetadata md) {
|
||||
protected ErrorType cloneWithMetadata(List<TypeMetadata> md) {
|
||||
return new ErrorType(originalType, tsym, md) {
|
||||
@Override
|
||||
public Type baseType() { return ErrorType.this.baseType(); }
|
||||
@ -2432,12 +2395,7 @@ public abstract class Type extends AnnoConstruct implements TypeMirror, PoolCons
|
||||
public UnknownType() {
|
||||
// Unknown is a synthesized internal type, so it cannot be
|
||||
// annotated.
|
||||
super(null, TypeMetadata.EMPTY);
|
||||
}
|
||||
|
||||
@Override
|
||||
public UnknownType cloneWithMetadata(TypeMetadata md) {
|
||||
throw new AssertionError("Cannot add metadata to an unknown type");
|
||||
super(null, List.nil());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2014, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -25,181 +25,55 @@
|
||||
|
||||
package com.sun.tools.javac.code;
|
||||
|
||||
import com.sun.tools.javac.util.Assert;
|
||||
import com.sun.tools.javac.util.List;
|
||||
import java.util.EnumMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import com.sun.tools.javac.util.ListBuffer;
|
||||
|
||||
/**
|
||||
* TypeMetadata is essentially an immutable {@code EnumMap<Entry.Kind, <? extends Entry>>}
|
||||
*
|
||||
* A metadata class represented by a subtype of Entry can express a property on a Type instance.
|
||||
* There should be at most one instance of an Entry per Entry.Kind on any given Type instance.
|
||||
*
|
||||
* Metadata classes of a specific kind are responsible for how they combine themselves.
|
||||
*
|
||||
* @implNote {@code Entry:combine} need not be commutative.
|
||||
* A type metadata is an object that can be stapled on a type. This is typically done using
|
||||
* {@link Type#addMetadata(TypeMetadata)}. Metadata associated to a type can also be removed,
|
||||
* typically using {@link Type#dropMetadata(Class)}. To drop <em>all</em> metadata from a given type,
|
||||
* the {@link Type#baseType()} method can also be used. This can be useful when comparing two
|
||||
* using reference equality (see also {@link Type#equalsIgnoreMetadata(Type)}).
|
||||
* <p>
|
||||
* There are no constraints on how a type metadata should be defined. Typically, a type
|
||||
* metadata will be defined as a small record, storing additional information (see {@link ConstantValue}).
|
||||
* In other cases, type metadata can be mutable and support complex state transitions
|
||||
* (see {@link Annotations}).
|
||||
* <p>
|
||||
* The only invariant the implementation requires is that there must be <em>one</em> metadata
|
||||
* of a given kind attached to a type, as this makes accessing and dropping metadata simpler.
|
||||
* If clients wish to store multiple metadata values that are logically related, they should
|
||||
* define a metadata type that collects such values in e.g. a list.
|
||||
*/
|
||||
public class TypeMetadata {
|
||||
public static final TypeMetadata EMPTY = new TypeMetadata();
|
||||
|
||||
private final EnumMap<Entry.Kind, Entry> contents;
|
||||
public sealed interface TypeMetadata {
|
||||
|
||||
/**
|
||||
* Create a new empty TypeMetadata map.
|
||||
* A type metadata object holding type annotations. This metadata needs to be mutable,
|
||||
* because type annotations are sometimes set in two steps. That is, a type can be created with
|
||||
* an empty set of annotations (e.g. during member enter). At some point later, the type
|
||||
* is then updated to contain the correct annotations. At this point we need to augment
|
||||
* the existing type (rather than creating a new one), as the type might already have been
|
||||
* saved inside other symbols.
|
||||
*/
|
||||
private TypeMetadata() {
|
||||
contents = new EnumMap<>(Entry.Kind.class);
|
||||
}
|
||||
record Annotations(ListBuffer<Attribute.TypeCompound> annotationBuffer) implements TypeMetadata {
|
||||
|
||||
/**
|
||||
* Create a new TypeMetadata map containing the Entry {@code elem}.
|
||||
*
|
||||
* @param elem the sole contents of this map
|
||||
*/
|
||||
public TypeMetadata(Entry elem) {
|
||||
this();
|
||||
Assert.checkNonNull(elem);
|
||||
contents.put(elem.kind(), elem);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a copy of TypeMetadata {@code other} with a shallow copy the other's metadata contents.
|
||||
*
|
||||
* @param other the TypeMetadata to copy contents from.
|
||||
*/
|
||||
public TypeMetadata(TypeMetadata other) {
|
||||
Assert.checkNonNull(other);
|
||||
contents = other.contents.clone();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a copy of this TypeMetadata with the metadata entry for {@code elem.kind()} combined
|
||||
* with {@code elem}.
|
||||
*
|
||||
* @param elem the new value
|
||||
* @return a new TypeMetadata updated with {@code Entry elem}
|
||||
*/
|
||||
public TypeMetadata combine(Entry elem) {
|
||||
Assert.checkNonNull(elem);
|
||||
|
||||
TypeMetadata out = new TypeMetadata(this);
|
||||
Entry.Kind key = elem.kind();
|
||||
if (contents.containsKey(key)) {
|
||||
out.add(key, this.contents.get(key).combine(elem));
|
||||
} else {
|
||||
out.add(key, elem);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a copy of this TypeMetadata with the metadata entry for all kinds from {@code other}
|
||||
* combined with the same kind from this.
|
||||
*
|
||||
* @param other the TypeMetadata to combine with this
|
||||
* @return a new TypeMetadata updated with all entries from {@code other}
|
||||
*/
|
||||
public TypeMetadata combineAll(TypeMetadata other) {
|
||||
Assert.checkNonNull(other);
|
||||
|
||||
TypeMetadata out = new TypeMetadata();
|
||||
Set<Entry.Kind> keys = new HashSet<>(contents.keySet());
|
||||
keys.addAll(other.contents.keySet());
|
||||
|
||||
for(Entry.Kind key : keys) {
|
||||
if (contents.containsKey(key)) {
|
||||
if (other.contents.containsKey(key)) {
|
||||
out.add(key, contents.get(key).combine(other.contents.get(key)));
|
||||
} else {
|
||||
out.add(key, contents.get(key));
|
||||
}
|
||||
} else if (other.contents.containsKey(key)) {
|
||||
out.add(key, other.contents.get(key));
|
||||
}
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a TypeMetadata with the metadata entry for {@code kind} removed.
|
||||
*
|
||||
* This may be the same instance or a new TypeMetadata.
|
||||
*
|
||||
* @param kind the {@code Kind} to remove metadata for
|
||||
* @return a new TypeMetadata without {@code Kind kind}
|
||||
*/
|
||||
public TypeMetadata without(Entry.Kind kind) {
|
||||
if (this == EMPTY || contents.get(kind) == null)
|
||||
return this;
|
||||
|
||||
TypeMetadata out = new TypeMetadata(this);
|
||||
out.contents.remove(kind);
|
||||
return out.contents.isEmpty() ? EMPTY : out;
|
||||
}
|
||||
|
||||
public Entry get(Entry.Kind kind) {
|
||||
return contents.get(kind);
|
||||
}
|
||||
|
||||
private void add(Entry.Kind kind, Entry elem) {
|
||||
contents.put(kind, elem);
|
||||
}
|
||||
|
||||
public interface Entry {
|
||||
|
||||
public enum Kind {
|
||||
ANNOTATIONS
|
||||
Annotations() {
|
||||
this(new ListBuffer<>());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the kind of metadata this object represents
|
||||
*/
|
||||
public Kind kind();
|
||||
Annotations(List<Attribute.TypeCompound> annotations) {
|
||||
this();
|
||||
annotationBuffer.appendList(annotations);
|
||||
}
|
||||
|
||||
/**
|
||||
* Combine this type metadata with another metadata of the
|
||||
* same kind.
|
||||
*
|
||||
* @param other The metadata with which to combine this one.
|
||||
* @return The combined metadata.
|
||||
*/
|
||||
public Entry combine(Entry other);
|
||||
List<Attribute.TypeCompound> annotations() {
|
||||
return annotationBuffer.toList();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A type metadata object holding type annotations.
|
||||
* A type metadata holding a constant value. This can be used to describe constant types,
|
||||
* such as the type of a string literal, or that of a numeric constant.
|
||||
*/
|
||||
public static class Annotations implements Entry {
|
||||
private List<Attribute.TypeCompound> annos;
|
||||
|
||||
public static final List<Attribute.TypeCompound> TO_BE_SET = List.nil();
|
||||
|
||||
public Annotations(List<Attribute.TypeCompound> annos) {
|
||||
this.annos = annos;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the type annotations contained in this metadata.
|
||||
*
|
||||
* @return The annotations.
|
||||
*/
|
||||
public List<Attribute.TypeCompound> getAnnotations() {
|
||||
return annos;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Annotations combine(Entry other) {
|
||||
Assert.check(annos == TO_BE_SET);
|
||||
annos = ((Annotations)other).annos;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Kind kind() { return Kind.ANNOTATIONS; }
|
||||
|
||||
@Override
|
||||
public String toString() { return "ANNOTATIONS [ " + annos + " ]"; }
|
||||
}
|
||||
record ConstantValue(Object value) implements TypeMetadata { }
|
||||
}
|
||||
|
@ -44,7 +44,7 @@ import com.sun.tools.javac.code.Attribute.RetentionPolicy;
|
||||
import com.sun.tools.javac.code.Lint.LintCategory;
|
||||
import com.sun.tools.javac.code.Source.Feature;
|
||||
import com.sun.tools.javac.code.Type.UndetVar.InferenceBound;
|
||||
import com.sun.tools.javac.code.TypeMetadata.Entry.Kind;
|
||||
import com.sun.tools.javac.code.TypeMetadata.Annotations;
|
||||
import com.sun.tools.javac.comp.AttrContext;
|
||||
import com.sun.tools.javac.comp.Check;
|
||||
import com.sun.tools.javac.comp.Enter;
|
||||
@ -2399,7 +2399,7 @@ public class Types {
|
||||
private TypeMapping<Boolean> erasure = new StructuralTypeMapping<Boolean>() {
|
||||
private Type combineMetadata(final Type s,
|
||||
final Type t) {
|
||||
if (t.getMetadata() != TypeMetadata.EMPTY) {
|
||||
if (t.getMetadata().nonEmpty()) {
|
||||
switch (s.getKind()) {
|
||||
case OTHER:
|
||||
case UNION:
|
||||
@ -2410,7 +2410,7 @@ public class Types {
|
||||
case VOID:
|
||||
case ERROR:
|
||||
return s;
|
||||
default: return s.cloneWithMetadata(s.getMetadata().without(Kind.ANNOTATIONS));
|
||||
default: return s.dropMetadata(Annotations.class);
|
||||
}
|
||||
} else {
|
||||
return s;
|
||||
@ -2437,7 +2437,7 @@ public class Types {
|
||||
Type erased = t.tsym.erasure(Types.this);
|
||||
if (recurse) {
|
||||
erased = new ErasedClassType(erased.getEnclosingType(),erased.tsym,
|
||||
t.getMetadata().without(Kind.ANNOTATIONS));
|
||||
t.dropMetadata(Annotations.class).getMetadata());
|
||||
return erased;
|
||||
} else {
|
||||
return combineMetadata(erased, t);
|
||||
|
@ -32,7 +32,7 @@ import com.sun.tools.javac.code.Kinds.KindSelector;
|
||||
import com.sun.tools.javac.code.Scope.WriteableScope;
|
||||
import com.sun.tools.javac.code.Source.Feature;
|
||||
import com.sun.tools.javac.code.Symbol.*;
|
||||
import com.sun.tools.javac.code.TypeMetadata.Entry.Kind;
|
||||
import com.sun.tools.javac.code.TypeMetadata.Annotations;
|
||||
import com.sun.tools.javac.comp.Check.CheckContext;
|
||||
import com.sun.tools.javac.resources.CompilerProperties.Errors;
|
||||
import com.sun.tools.javac.resources.CompilerProperties.Fragments;
|
||||
@ -1049,7 +1049,10 @@ public class Annotate {
|
||||
typeAnnotation(() -> {
|
||||
List<Attribute.TypeCompound> compounds = fromAnnotations(annotations);
|
||||
Assert.check(annotations.size() == compounds.size());
|
||||
storeAt.getMetadataOfKind(Kind.ANNOTATIONS).combine(new TypeMetadata.Annotations(compounds));
|
||||
// the type already has annotation metadata, but it's empty
|
||||
Annotations metadata = storeAt.getMetadata(Annotations.class).orElseThrow(AssertionError::new);
|
||||
Assert.check(metadata.annotationBuffer().isEmpty());
|
||||
metadata.annotationBuffer().appendList(compounds);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -46,7 +46,6 @@ import com.sun.tools.javac.code.Scope.WriteableScope;
|
||||
import com.sun.tools.javac.code.Source.Feature;
|
||||
import com.sun.tools.javac.code.Symbol.*;
|
||||
import com.sun.tools.javac.code.Type.*;
|
||||
import com.sun.tools.javac.code.TypeMetadata.Annotations;
|
||||
import com.sun.tools.javac.code.Types.FunctionDescriptorLookupError;
|
||||
import com.sun.tools.javac.comp.ArgumentAttr.LocalCacheContext;
|
||||
import com.sun.tools.javac.comp.Check.CheckContext;
|
||||
@ -5210,7 +5209,7 @@ public class Attr extends JCTree.Visitor {
|
||||
public void visitAnnotatedType(JCAnnotatedType tree) {
|
||||
attribAnnotationTypes(tree.annotations, env);
|
||||
Type underlyingType = attribType(tree.underlyingType, env);
|
||||
Type annotatedType = underlyingType.annotatedType(Annotations.TO_BE_SET);
|
||||
Type annotatedType = underlyingType.preannotatedType();
|
||||
|
||||
if (!env.info.isNewClass)
|
||||
annotate.annotateTypeSecondStage(tree, tree.annotations, annotatedType);
|
||||
|
@ -221,17 +221,12 @@ public class DeferredAttr extends JCTree.Visitor {
|
||||
SpeculativeCache speculativeCache;
|
||||
|
||||
DeferredType(JCExpression tree, Env<AttrContext> env) {
|
||||
super(null, TypeMetadata.EMPTY);
|
||||
super(null, List.nil());
|
||||
this.tree = tree;
|
||||
this.env = attr.copyEnv(env);
|
||||
this.speculativeCache = new SpeculativeCache();
|
||||
}
|
||||
|
||||
@Override
|
||||
public DeferredType cloneWithMetadata(TypeMetadata md) {
|
||||
throw new AssertionError("Cannot add metadata to a deferred type");
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeTag getTag() {
|
||||
return DEFERRED;
|
||||
|
@ -2925,7 +2925,7 @@ public class ClassReader {
|
||||
private final Name name;
|
||||
|
||||
public ProxyType(int index) {
|
||||
super(syms.noSymbol, TypeMetadata.EMPTY);
|
||||
super(syms.noSymbol, List.nil());
|
||||
this.name = poolReader.getName(index);
|
||||
}
|
||||
|
||||
@ -2934,11 +2934,6 @@ public class ClassReader {
|
||||
return TypeTag.NONE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Type cloneWithMetadata(TypeMetadata metadata) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public Type resolve() {
|
||||
return name.map(ClassReader.this::sigToType);
|
||||
}
|
||||
|
@ -53,13 +53,13 @@ class UninitializedType extends Type.DelegatedType {
|
||||
|
||||
public final int offset; // PC where allocation took place
|
||||
private UninitializedType(TypeTag tag, Type qtype, int offset,
|
||||
TypeMetadata metadata) {
|
||||
List<TypeMetadata> metadata) {
|
||||
super(tag, qtype, metadata);
|
||||
this.offset = offset;
|
||||
}
|
||||
|
||||
@Override
|
||||
public UninitializedType cloneWithMetadata(final TypeMetadata md) {
|
||||
protected UninitializedType cloneWithMetadata(final List<TypeMetadata> md) {
|
||||
return new UninitializedType(tag, qtype, offset, md);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user