Skip to content

Javaparser & ElimRepeated fixes & Annotation-fixes #213

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 46 commits into from
Nov 24, 2014
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
1e1f260
Add the right constructor to Java annotations
odersky Oct 10, 2014
9760fb7
Testcase that shows bug in ElimRepeated.
DarkDimius Oct 11, 2014
cda5add
Fix elimRepeated not transforming annotations.
DarkDimius Oct 11, 2014
7e7b2f2
Add Id's to types.
DarkDimius Oct 29, 2014
3c14254
Fix typeAssigner ignoring existence of JavaSeqLiteral
DarkDimius Oct 29, 2014
9bcb3a0
Fix TypeErasure.sigName erasing java repeated params to Seq
DarkDimius Oct 29, 2014
cbe4f0a
Fix underlyingIfRepeated always assuming Scala repeated.
DarkDimius Oct 29, 2014
3b0349b
FunProtoTyped to be used when args are known to be typed
DarkDimius Oct 30, 2014
998a5c8
readAnnotationContents that should be able to resolve overloaded cons…
DarkDimius Oct 30, 2014
12209dd
Allow resolving overloads without inferring views.
DarkDimius Oct 30, 2014
68dfe2a
Fix StackOveflow due to implicit resolution in readAnnotationContents
DarkDimius Oct 30, 2014
11449db
Infer if overloading resolution should trigger implicit search.
DarkDimius Oct 30, 2014
edee880
Dotty typer deviation triggered in Unpickler
DarkDimius Oct 30, 2014
a273c3f
Fix ElimRepeated not transforming modifiers in tree.
DarkDimius Nov 3, 2014
5a15ee9
Rename PolyType.copy method. It clashes with generated one.
DarkDimius Nov 3, 2014
e935eaa
#204 check for global uniqueness of definitions.
DarkDimius Nov 3, 2014
35bf914
Allow checking that trees and their defined symbols have modifiers in…
DarkDimius Nov 3, 2014
cc1d36f
Show full name of doubly defined symbols
DarkDimius Nov 3, 2014
03627e7
Initial implementation of Java scanner and parser
olhotak Sep 4, 2014
ade0565
desugar Java repeated parms into an Array instead of Seq
olhotak Oct 8, 2014
07c4c96
Java Select: try typing as both SelectFromTypeTree and Select
olhotak Oct 8, 2014
2c5959b
support running java-interop tests
olhotak Oct 8, 2014
ef7fc8f
make elimrepeated addVarArgsBridge at thisTransformer instead of this…
olhotak Oct 9, 2014
95e845b
add mapping ENUM -> Enum to PickleBuffer
olhotak Oct 10, 2014
36cb102
add comment explaining why checkValue skips Java compilation units
olhotak Oct 10, 2014
6ef59b1
add comment to explain why refctx passed explicitly to selectionType
olhotak Oct 10, 2014
95d7ff8
remove debugging println
olhotak Oct 10, 2014
7983a09
Flags.Static renamed to JavaStatic
olhotak Oct 29, 2014
baaf851
fix calls to tree copier that now requires multiple parameter lists
olhotak Oct 29, 2014
44ae006
make annotation classes abstract (since they are interfaces)
olhotak Oct 29, 2014
f1602ab
For Java constructors, do not move out to ctx.outer
olhotak Oct 30, 2014
4dabffd
create dummy first constructor for Java classes
olhotak Oct 29, 2014
dd6a7e7
don't try to make a body for a setter of a Java field
olhotak Oct 30, 2014
d6fdc84
Extract AnnotationTransformer functionality from ElimRepeated to a trait
DarkDimius Nov 4, 2014
cc8ca00
AnnotationTransformer now also transforms types
DarkDimius Nov 4, 2014
32954ba
Extracting ApplyOverloaded to be reused in UnPickler and ClassfileParser
DarkDimius Nov 4, 2014
e2c5fcd
Java annotations parsing problem
DarkDimius Nov 4, 2014
3bb70e8
Annotations have JavaSeqLiterals inside.
DarkDimius Nov 17, 2014
22c9a9b
Add handling of parsed annotations to applyOverloaded.
DarkDimius Nov 17, 2014
38cebe0
Adapting branch to absence of modifiers in trees.
DarkDimius Nov 17, 2014
4b71995
Fixing memoize transforming java fields.
DarkDimius Nov 17, 2014
265ac7a
Moving java tests to pos
DarkDimius Nov 17, 2014
ec104ef
Enabling java tests
DarkDimius Nov 17, 2014
31aef81
Address reviewer feedback: restructure applyOverloaded.
DarkDimius Nov 20, 2014
14654c3
Drop java-defined trees in FirstTransform
DarkDimius Nov 20, 2014
859a7fe
Do not skip packages in FirstTransform
DarkDimius Nov 22, 2014
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion src/dotty/tools/dotc/TypeErasure.scala
Original file line number Diff line number Diff line change
Expand Up @@ -95,8 +95,9 @@ object TypeErasure {
def erasure(tp: Type)(implicit ctx: Context): Type = scalaErasureFn(tp)(erasureCtx)
def semiErasure(tp: Type)(implicit ctx: Context): Type = semiErasureFn(tp)(erasureCtx)
def sigName(tp: Type, isJava: Boolean)(implicit ctx: Context): TypeName = {
val seqClass = if(isJava) defn.ArrayClass else defn.SeqClass
val normTp =
if (tp.isRepeatedParam) tp.translateParameterized(defn.RepeatedParamClass, defn.SeqClass)
if (tp.isRepeatedParam) tp.translateParameterized(defn.RepeatedParamClass, seqClass)
else tp
(if (isJava) javaSigFn else scalaSigFn).sigName(normTp)(erasureCtx)
}
Expand Down
7 changes: 4 additions & 3 deletions src/dotty/tools/dotc/ast/Desugar.scala
Original file line number Diff line number Diff line change
Expand Up @@ -771,11 +771,12 @@ object desugar {
else // l.op(r), or val x = r; l.op(x), plus handle named args specially
makeBinop(l, op, r)
case PostfixOp(t, op) =>
if ((ctx.mode is Mode.Type) && op == nme.raw.STAR)
if ((ctx.mode is Mode.Type) && op == nme.raw.STAR) {
val seqClass = if (ctx.compilationUnit.isJava) defn.ArrayClass else defn.SeqClass
Annotated(
New(ref(defn.RepeatedAnnot.typeRef), Nil :: Nil),
AppliedTypeTree(ref(defn.SeqClass.typeRef), t))
else {
AppliedTypeTree(ref(seqClass.typeRef), t))
} else {
assert(ctx.mode.isExpr, ctx.mode)
Select(t, op)
}
Expand Down
49 changes: 47 additions & 2 deletions src/dotty/tools/dotc/ast/tpd.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package dotty.tools
package dotc
package ast

import dotty.tools.dotc.typer.ProtoTypes.FunProtoTyped
import transform.SymUtils._
import core._
import util.Positions._, Types._, Contexts._, Constants._, Names._, Flags._
Expand Down Expand Up @@ -126,8 +127,8 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
if (tpe derivesFrom defn.SeqClass) SeqLiteral(elems) else JavaSeqLiteral(elems)

def JavaSeqLiteral(elems: List[Tree])(implicit ctx: Context): SeqLiteral =
new untpd.JavaSeqLiteral(elems)
.withType(defn.ArrayClass.typeRef.appliedTo(ctx.typeComparer.lub(elems.tpes)))
ta.assignType(new untpd.JavaSeqLiteral(elems), elems)


def TypeTree(original: Tree)(implicit ctx: Context): TypeTree =
TypeTree(original.tpe, original)
Expand Down Expand Up @@ -677,6 +678,50 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
Throw(New(defn.ClassCastExceptionClass.typeRef, Nil)) withPos tree.pos
}
}

def applyOverloaded(receiver: Tree, method: TermName, args: List[Tree], targs: List[Type], expectedType: Type, isAnnotConstructor: Boolean = false)(implicit ctx: Context): Tree = {
val typer = ctx.typer
val proto = new FunProtoTyped(args, expectedType, typer)
val alts = receiver.tpe.member(method).alternatives.map(_.termRef)

val alternatives = ctx.typer.resolveOverloaded(alts, proto, Nil)
assert(alternatives.size == 1) // this is parsed from bytecode tree. there's nothing user can do about it

val selected = alternatives.head
val fun = receiver
.select(TermRef.withSig(receiver.tpe.normalizedPrefix, selected.termSymbol.asTerm))
.appliedToTypes(targs)

def adaptLastArg(lastParam: Tree, expectedType: Type) = {
if (isAnnotConstructor && !(lastParam.tpe <:< expectedType)) {
val defn = ctx.definitions
val prefix = args.take(selected.widen.paramTypess.head.size - 1)
expectedType match {
case defn.ArrayType(el) =>
lastParam.tpe match {
case defn.ArrayType(el2) if (el2 <:< el) =>
// we have a JavaSeqLiteral with a more precise type
// we cannot construct a tree as JavaSeqLiteral infered to precise type
// if we add typed than it would be both type-correct and
// will pass Ycheck
prefix ::: List(tpd.Typed(lastParam, TypeTree(defn.ArrayType(el))))
case _ =>
???
}
case _ => args
}
} else args
}

val callArgs: List[Tree] = if(args.isEmpty) Nil else {
val expectedType = selected.widen.paramTypess.head.last
val lastParam = args.last
adaptLastArg(lastParam, expectedType)
}

val apply = untpd.Apply(fun, callArgs)
new typer.ApplyToTyped(apply, fun, selected, callArgs, expectedType).result.asInstanceOf[Tree] // needed to handle varargs
}

@tailrec
def sameTypes(trees: List[tpd.Tree], trees1: List[tpd.Tree]): Boolean = {
Expand Down
1 change: 1 addition & 0 deletions src/dotty/tools/dotc/config/ScalaSettings.scala
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ class ScalaSettings extends Settings.SettingGroup {
val Yhelp = BooleanSetting("-Y", "Print a synopsis of private options.")
val browse = PhasesSetting("-Ybrowse", "Browse the abstract syntax tree after")
val Ycheck = PhasesSetting("-Ycheck", "Check the tree at the end of")
val YcheckMods = BooleanSetting("-Ycheck-mods", "Check that symbols and their defining trees have modifiers in sync")
val YcheckTypedTrees = BooleanSetting("-YcheckTypedTrees", "Check all constructured typed trees for type correctness")
val Yshow = PhasesSetting("-Yshow", "(Requires -Xshow-class or -Xshow-object) Show after")
val Xcloselim = BooleanSetting("-Yclosure-elim", "Perform closure elimination.")
Expand Down
15 changes: 15 additions & 0 deletions src/dotty/tools/dotc/core/Annotations.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ package core

import Symbols._, Types._, util.Positions._, Contexts._, Constants._, ast.tpd._
import config.ScalaVersion
import StdNames._
import dotty.tools.dotc.ast.{tpd, untpd}
import dotty.tools.dotc.typer.ProtoTypes.FunProtoTyped

object Annotations {

Expand Down Expand Up @@ -61,12 +64,24 @@ object Annotations {
def apply(atp: Type, args: List[Tree])(implicit ctx: Context): Annotation =
apply(New(atp, args))

private def resolveConstructor(atp: Type, args:List[Tree])(implicit ctx: Context): Tree = {
val targs = atp.argTypes
tpd.applyOverloaded(New(atp withoutArgs targs), nme.CONSTRUCTOR, args, targs, atp, isAnnotConstructor = true)
}

def applyResolve(atp: Type, args: List[Tree])(implicit ctx: Context): Annotation = {
apply(resolveConstructor(atp, args))
}

def deferred(sym: Symbol, treeFn: Context => Tree)(implicit ctx: Context): Annotation =
new LazyAnnotation(sym)(treeFn)

def deferred(atp: Type, args: List[Tree])(implicit ctx: Context): Annotation =
deferred(atp.classSymbol, implicit ctx => New(atp, args))

def deferredResolve(atp: Type, args: List[Tree])(implicit ctx: Context): Annotation =
deferred(atp.classSymbol, implicit ctx => resolveConstructor(atp, args))

def makeAlias(sym: TermSymbol)(implicit ctx: Context) =
apply(defn.AliasAnnot, List(
ref(TermRef.withSigAndDenot(sym.owner.thisType, sym.name, sym.signature, sym))))
Expand Down
11 changes: 10 additions & 1 deletion src/dotty/tools/dotc/core/Flags.scala
Original file line number Diff line number Diff line change
Expand Up @@ -318,7 +318,7 @@ object Flags {
/** An unpickled Scala 2.x class */
final val Scala2x = typeFlag(26, "<scala-2.x>")

/** A method that has default params */ // TODO: drop
/** A method that has default params */
final val DefaultParameterized = termFlag(27, "<defaultparam>")

/** Symbol is initialized to the default value, e.g. var x: T = _ */
Expand Down Expand Up @@ -356,6 +356,12 @@ object Flags {
/** Symbol is a Java-style varargs method */
final val JavaVarargs = termFlag(37, "<varargs>")

/** Symbol is a Java default method */
final val DefaultMethod = termFlag(38, "<defaultmethod>")

/** Symbol is a Java enum */
final val Enum = commonFlag(40, "<enum>")

// Flags following this one are not pickled

/** Symbol always defines a fresh named type */
Expand Down Expand Up @@ -547,6 +553,9 @@ object Flags {

/** A Java interface, potentially with default methods */
final val JavaTrait = allOf(JavaDefined, Trait, NoInits)

/** A Java interface */
final val JavaInterface = allOf(JavaDefined, Trait)

/** A Java companion object */
final val JavaModule = allOf(JavaDefined, Module)
Expand Down
5 changes: 4 additions & 1 deletion src/dotty/tools/dotc/core/TypeApplications.scala
Original file line number Diff line number Diff line change
Expand Up @@ -284,7 +284,10 @@ class TypeApplications(val self: Type) extends AnyVal {
* or, if isJava is true, Array type, else the type itself.
*/
def underlyingIfRepeated(isJava: Boolean)(implicit ctx: Context): Type =
if (self.isRepeatedParam) translateParameterized(defn.RepeatedParamClass, defn.SeqClass)
if (self.isRepeatedParam) {
val seqClass = if(isJava) defn.ArrayClass else defn.SeqClass
translateParameterized(defn.RepeatedParamClass, seqClass)
}
else self

/** If this is an encoding of a (partially) applied type, return its arguments,
Expand Down
17 changes: 14 additions & 3 deletions src/dotty/tools/dotc/core/Types.scala
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ object Types {

private var recCount = 0 // used temporarily for debugging. TODO: remove

private var nextId = 0

/** The class of types.
* The principal subclasses and sub-objects are as follows:
*
Expand Down Expand Up @@ -70,6 +72,13 @@ object Types {

// ----- Tests -----------------------------------------------------

val uniqId = {
nextId = nextId + 1
// if(nextId == 19555)
// println("foo")
nextId
}

/** Is this type different from NoType? */
def exists: Boolean = true

Expand Down Expand Up @@ -1965,7 +1974,9 @@ object Types {
def fromSymbols(params: List[Symbol], resultType: Type)(implicit ctx: Context) = {
def paramInfo(param: Symbol): Type = param.info match {
case AnnotatedType(annot, tp) if annot matches defn.RepeatedAnnot =>
tp.translateParameterized(defn.SeqClass, defn.RepeatedParamClass)
val typeSym = param.info.typeSymbol.asClass
assert(typeSym == defn.SeqClass || typeSym == defn.ArrayClass)
tp.translateParameterized(typeSym, defn.RepeatedParamClass)
case tp =>
tp
}
Expand Down Expand Up @@ -2024,9 +2035,9 @@ object Types {

def derivedPolyType(paramNames: List[TypeName], paramBounds: List[TypeBounds], restpe: Type)(implicit ctx: Context) =
if ((paramNames eq this.paramNames) && (paramBounds eq this.paramBounds) && (restpe eq this.resultType)) this
else copy(paramNames, paramBounds, restpe)
else duplicate(paramNames, paramBounds, restpe)

def copy(paramNames: List[TypeName], paramBounds: List[TypeBounds], restpe: Type)(implicit ctx: Context) =
def duplicate(paramNames: List[TypeName] = this.paramNames, paramBounds: List[TypeBounds] = this.paramBounds, restpe: Type)(implicit ctx: Context) =
PolyType(paramNames)(
x => paramBounds mapConserve (_.subst(this, x).bounds),
x => restpe.subst(this, x))
Expand Down
44 changes: 42 additions & 2 deletions src/dotty/tools/dotc/core/pickling/ClassfileParser.scala
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,7 @@ class ClassfileParser(
for (i <- 0 until in.nextChar) parseMember(method = false)
for (i <- 0 until in.nextChar) parseMember(method = true)
classInfo = parseAttributes(classRoot.symbol, classInfo)
if (isAnnotation) addAnnotationConstructor(classInfo)
setClassInfo(classRoot, classInfo)
setClassInfo(moduleRoot, staticInfo)
}
Expand Down Expand Up @@ -421,7 +422,7 @@ class ClassfileParser(
case None => hasError = true
}
if (hasError) None
else if (skip) None else Some(SeqLiteral(arr.toList))
else if (skip) None else Some(JavaSeqLiteral(arr.toList))
case ANNOTATION_TAG =>
parseAnnotation(index, skip) map (_.tree)
}
Expand All @@ -443,7 +444,7 @@ class ClassfileParser(
}
}
if (hasError || skip) None
else Some(Annotation.deferred(attrType, argbuf.toList))
else Some(Annotation.deferredResolve(attrType, argbuf.toList))
} catch {
case f: FatalError => throw f // don't eat fatal errors, they mean a class was not found
case ex: Throwable =>
Expand Down Expand Up @@ -551,6 +552,45 @@ class ClassfileParser(
newType
}

/** Add a synthetic constructor and potentially also default getters which
* reflects the fields of the annotation with given `classInfo`.
* Annotations in Scala are assumed to get all their arguments as constructor
* parameters. For Java annotations we need to fake it by making up the constructor.
* Note that default getters have type Nothing. That's OK because we need
* them only to signal that the corresponding parameter is optional.
*/
def addAnnotationConstructor(classInfo: Type, tparams: List[Symbol] = Nil)(implicit ctx: Context): Unit = {
def addDefaultGetter(attr: Symbol, n: Int) =
ctx.newSymbol(
owner = moduleRoot.symbol,
name = nme.CONSTRUCTOR.defaultGetterName(n),
flags = attr.flags & Flags.AccessFlags,
info = defn.NothingType).entered

classInfo match {
case classInfo @ TempPolyType(tparams, restpe) if tparams.isEmpty =>
addAnnotationConstructor(restpe, tparams)
case classInfo: TempClassInfoType =>
val attrs = classInfo.decls.toList.filter(_.isTerm)
val targs = tparams.map(_.typeRef)
val methType = MethodType(
attrs.map(_.name.asTermName),
attrs.map(_.info.resultType),
classRoot.typeRef.appliedTo(targs))
val constr = ctx.newSymbol(
owner = classRoot.symbol,
name = nme.CONSTRUCTOR,
flags = Flags.Synthetic,
info = if (tparams.isEmpty) methType else TempPolyType(tparams, methType)
).entered
for ((attr, i) <- attrs.zipWithIndex)
if (attr.hasAnnotation(defn.AnnotationDefaultAnnot)) {
constr.setFlag(Flags.HasDefaultParams)
addDefaultGetter(attr, i)
}
}
}

/** Enter own inner classes in the right scope. It needs the scopes to be set up,
* and implicitly current class' superclasses.
*/
Expand Down
3 changes: 2 additions & 1 deletion src/dotty/tools/dotc/core/pickling/PickleBuffer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,8 @@ object PickleBuffer {
SPECIALIZED -> Specialized,
DEFAULTINIT -> DefaultInit,
VBRIDGE -> VBridge,
VARARGS -> JavaVarargs)
VARARGS -> JavaVarargs,
ENUM -> Enum)

// generate initial maps from Scala flags to Dotty flags
val termMap, typeMap = new Array[Long](64)
Expand Down
32 changes: 20 additions & 12 deletions src/dotty/tools/dotc/core/pickling/UnPickler.scala
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,9 @@ import java.lang.Double.longBitsToDouble

import Contexts._, Symbols._, Types._, Scopes._, SymDenotations._, Names._, NameOps._
import StdNames._, Denotations._, NameOps._, Flags._, Constants._, Annotations._
import dotty.tools.dotc.typer.ProtoTypes.{FunProtoTyped, FunProto}
import util.Positions._
import ast.Trees, ast.tpd._, ast.untpd
import dotty.tools.dotc.ast.{tpd, Trees, untpd}, ast.tpd._
import printing.Texts._
import printing.Printer
import io.AbstractFile
Expand Down Expand Up @@ -815,19 +816,26 @@ class UnPickler(bytes: Array[Byte], classRoot: ClassDenotation, moduleClassRoot:
*/
protected def readAnnotationContents(end: Int)(implicit ctx: Context): Tree = {
val atp = readTypeRef()
val args = new ListBuffer[Tree]
while (readIndex != end) {
val argref = readNat()
args += {
if (isNameEntry(argref)) {
val name = at(argref, readName)
val arg = readClassfileAnnotArg(readNat())
NamedArg(name.asTermName, arg)
} else readAnnotArg(argref)
val args = {
val t = new ListBuffer[Tree]

while (readIndex != end) {
val argref = readNat()
t += {
if (isNameEntry(argref)) {
val name = at(argref, readName)
val arg = readClassfileAnnotArg(readNat())
NamedArg(name.asTermName, arg)
} else readAnnotArg(argref)
}
}
t.toList
}
New(atp, args.toList)
}
// println(atp)
val targs = atp.argTypes

tpd.applyOverloaded(tpd.New(atp withoutArgs targs), nme.CONSTRUCTOR, args, targs, atp)
}

/** Read an annotation and as a side effect store it into
* the symbol it requests. Called at top-level, for all
Expand Down
Loading