Skip to content

Commit

Permalink
Add more tests, checks for flags and improve docs
Browse files Browse the repository at this point in the history
  • Loading branch information
jchyb committed Jan 10, 2025
1 parent bf14f5b commit 85fdd02
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 22 deletions.
15 changes: 14 additions & 1 deletion compiler/src/scala/quoted/runtime/impl/QuotesImpl.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2687,6 +2687,7 @@ class QuotesImpl private (using val ctx: Context) extends Quotes, QuoteUnpickler
assert(!clsPrivateWithin.exists || clsPrivateWithin.isType, "clsPrivateWithin must be a type symbol or `Symbol.noSymbol`")
assert(!conPrivateWithin.exists || conPrivateWithin.isType, "consPrivateWithin must be a type symbol or `Symbol.noSymbol`")
checkValidFlags(clsFlags.toTypeFlags, Flags.validClassFlags)
checkValidFlags(conFlags, Flags.validClassConstructorFlags)
val cls = dotc.core.Symbols.newNormalizedClassSymbolUsingClassSymbolinParents(
owner,
name.toTypeName,
Expand Down Expand Up @@ -2728,12 +2729,14 @@ class QuotesImpl private (using val ctx: Context) extends Quotes, QuoteUnpickler
}
for ((name, tpe, isType, clauseIdx), elementIdx) <- getParamAccessors(methodType, 0) do
if isType then
checkValidFlags(conParamFlags(clauseIdx)(elementIdx), Flags.validClassTypeParamFlags)
val symbol = dotc.core.Symbols.newSymbol(cls, name.toTypeName, Flags.Param | Flags.Deferred | Flags.Private | Flags.PrivateLocal | Flags.Local | conParamFlags(clauseIdx)(elementIdx), tpe, Symbol.noSymbol)
paramRefMap.addOne(elementIdx, symbol)
cls.enter(symbol)
else
checkValidFlags(conParamFlags(clauseIdx)(elementIdx), Flags.validClassTermParamFlags)
val fixedType = paramRefRemapper(tpe)
cls.enter(dotc.core.Symbols.newSymbol(cls, name.toTermName, Flags.ParamAccessor | conParamFlags(clauseIdx)(elementIdx), fixedType, Symbol.noSymbol)) // set privateWithin
cls.enter(dotc.core.Symbols.newSymbol(cls, name.toTermName, Flags.ParamAccessor | conParamFlags(clauseIdx)(elementIdx), fixedType, Symbol.noSymbol)) // TODO set privateWithin?
for sym <- decls(cls) do cls.enter(sym)
cls

Expand Down Expand Up @@ -3147,6 +3150,16 @@ class QuotesImpl private (using val ctx: Context) extends Quotes, QuoteUnpickler
// Keep: aligned with Quotes's `newClass`
private[QuotesImpl] def validClassFlags: Flags = Private | Protected | PrivateLocal | Local | Final | Trait | Abstract // AbsOverride, Open

// Keep: aligned with Quote's 'newClass'
// Private constructor would be currently useless, but if we decide to add a way to register companions in the future it might be useful
private[QuotesImpl] def validClassConstructorFlags: Flags = Synthetic | Method | Private | Protected | PrivateLocal | Local

// Keep: aligned with Quotes's `newClass`
private[QuotesImpl] def validClassTypeParamFlags: Flags = Param | Deferred | Private | PrivateLocal | Local

// Keep: aligned with Quotes's `newClass`
private[QuotesImpl] def validClassTermParamFlags: Flags = ParamAccessor | Private | Protected | PrivateLocal | Local

end Flags

given FlagsMethods: FlagsMethods with
Expand Down
55 changes: 34 additions & 21 deletions library/src/scala/quoted/Quotes.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3837,10 +3837,9 @@ trait Quotes { self: runtime.QuoteUnpickler & runtime.QuoteMatching =>
* @note As a macro can only splice code into the point at which it is expanded, all generated symbols must be
* direct or indirect children of the reflection context's owner.
*/
// TODO: add flags and privateWithin
@experimental def newClass(owner: Symbol, name: String, parents: List[TypeRepr], decls: Symbol => List[Symbol], selfType: Option[TypeRepr]): Symbol

/** Generates a new class symbol for a class with a public constructor.
/** Generates a new class symbol for a class with a public single term clause constructor.
*
* @param owner The owner of the class
* @param name The name of the class
Expand All @@ -3851,7 +3850,13 @@ trait Quotes { self: runtime.QuoteUnpickler & runtime.QuoteMatching =>
* @param conParamNames constructor parameter names.
* @param conParamTypes constructor parameter types.
*
* Parameters can be obtained via classSymbol.memberField
* Parameters assigned by the constructor can be obtained via `classSymbol.memberField`.
* This symbol starts without an accompanying definition.
* It is the meta-programmer's responsibility to provide exactly one corresponding definition by passing
* this symbol to the ClassDef constructor.
*
* @note As a macro can only splice code into the point at which it is expanded, all generated symbols must be
* direct or indirect children of the reflection context's owner.
*/
@experimental def newClass(
owner: Symbol,
Expand All @@ -3864,24 +3869,32 @@ trait Quotes { self: runtime.QuoteUnpickler & runtime.QuoteMatching =>
conParamTypes: List[TypeRepr]
): Symbol

/**
*
*
* @param owner The owner of the class
* @param name The name of the class
* @param parents Function returning the parent classes of the class. The first parent must not be a trait
* Takes the constructed class symbol as an argument. Calling `cls.typeRef.asType` as part of this function will lead to cyclic reference errors.
* @param decls The member declarations of the class provided the symbol of this class
* @param selfType The self type of the class if it has one
* @param clsFlags extra flags with which the class symbol should be constructed
* @param clsPrivateWithin the symbol within which this new class symbol should be private. May be noSymbol
* @param conMethodType The MethodOrPoly type representing the type of the constructor.
* PolyType may only represent the first clause of the constructor.
* @param conFlags extra flags with which the constructor symbol should be constructed
* @param conPrivateWithin the symbol within which the constructor for this new class symbol should be private. May be noSymbol.
* @param conParamFlags extra flags with which the constructor parameter symbols should be constructed. Must match the shape of `conMethodType`.
*
*/
/** Generates a new class symbol with a constructor of the shape signified by a passed PolyOrMethod parameter.
* TODO example with PolyType
*
* @param owner The owner of the class
* @param name The name of the class
* @param parents Function returning the parent classes of the class. The first parent must not be a trait
* Takes the constructed class symbol as an argument. Calling `cls.typeRef.asType` as part of this function will lead to cyclic reference errors.
* @param decls The member declarations of the class provided the symbol of this class
* @param selfType The self type of the class if it has one
* @param clsFlags extra flags with which the class symbol should be constructed
* @param clsPrivateWithin the symbol within which this new class symbol should be private. May be noSymbol
* @param conMethodType Function returning MethodOrPoly type representing the type of the constructor.
* Takes the result type as parameter which must be returned from the innermost MethodOrPoly.
* PolyType may only represent the first clause of the constructor.
* @param conFlags extra flags with which the constructor symbol should be constructed
* @param conPrivateWithin the symbol within which the constructor for this new class symbol should be private. May be noSymbol.
* @param conParamFlags extra flags with which the constructor parameter symbols should be constructed. Must match the shape of `conMethodType`.
*
* Term and type parameters assigned by the constructor can be obtained via `classSymbol.memberField`/`classSymbol.memberType`.
* This symbol starts without an accompanying definition.
* It is the meta-programmer's responsibility to provide exactly one corresponding definition by passing
* this symbol to the ClassDef constructor.
*
* @note As a macro can only splice code into the point at which it is expanded, all generated symbols must be
* direct or indirect children of the reflection context's owner.
*/
@experimental def newClass(
owner: Symbol,
name: String,
Expand Down

0 comments on commit 85fdd02

Please sign in to comment.