From 1d36be9b0023e6061e7d90c440af01a3c7bacd32 Mon Sep 17 00:00:00 2001 From: Mark Harrah Date: Sat, 21 May 2011 21:14:42 -0400 Subject: [PATCH] properly handle nested class cycles in Java sources, fixes #22 --- compile/api/ClassToAPI.scala | 24 +++++++++++-------- .../java/basic/src/main/java/test/O2.java | 10 ++++++++ .../java/basic/src/main/java/test/Outer.java | 8 +++++++ 3 files changed, 32 insertions(+), 10 deletions(-) create mode 100644 sbt/src/sbt-test/java/basic/src/main/java/test/O2.java create mode 100644 sbt/src/sbt-test/java/basic/src/main/java/test/Outer.java diff --git a/compile/api/ClassToAPI.scala b/compile/api/ClassToAPI.scala index 57dadfe77..7c82fc0ac 100644 --- a/compile/api/ClassToAPI.scala +++ b/compile/api/ClassToAPI.scala @@ -5,13 +5,14 @@ package sbt import xsbti.api import xsbti.SafeLazy import SafeLazy.strict + import collection.mutable object ClassToAPI { def apply(c: Seq[Class[_]]): api.Source = { val pkgs = packages(c).map(p => new api.Package(p)) - val defs = c.filter(isTopLevel).flatMap(toDefinitions) + val defs = c.filter(isTopLevel).flatMap(toDefinitions(new mutable.HashMap)) new api.Source(pkgs.toArray, defs.toArray) } @@ -21,7 +22,10 @@ object ClassToAPI def isTopLevel(c: Class[_]): Boolean = c.getEnclosingClass eq null - def toDefinitions(c: Class[_]): Seq[api.ClassLike] = + type ClassMap = mutable.Map[String, Seq[api.ClassLike]] + def toDefinitions(cmap: ClassMap)(c: Class[_]): Seq[api.ClassLike] = + cmap.getOrElseUpdate(c.getName, toDefinitions0(c, cmap)) + def toDefinitions0(c: Class[_], cmap: ClassMap): Seq[api.ClassLike] = { import api.DefinitionType.{ClassDef, Module, Trait} val enclPkg = packageName(c) @@ -30,24 +34,24 @@ object ClassToAPI val annots = annotations(c.getAnnotations) val name = c.getName val tpe = if(Modifier.isInterface(c.getModifiers)) Trait else ClassDef - lazy val (static, instance) = structure(c, enclPkg) + lazy val (static, instance) = structure(c, enclPkg, cmap) val cls = new api.ClassLike(tpe, strict(Empty), lzy(instance), typeParameters(c.getTypeParameters), name, acc, mods, annots) - def makeStatic(s: api.Structure) = - new api.ClassLike(Module, strict(Empty), strict(s), Array(), name, acc, mods, annots) - cls :: static.map(makeStatic).toList + val stat = new api.ClassLike(Module, strict(Empty), lzy(static), Array(), name, acc, mods, annots) + val defs = cls :: stat :: Nil + cmap(c.getName) = defs + defs } - def structure(c: Class[_], enclPkg: Option[String]): (Option[api.Structure], api.Structure) = + def structure(c: Class[_], enclPkg: Option[String], cmap: ClassMap): (api.Structure, api.Structure) = { val methods = mergeMap(c, c.getMethods, c.getDeclaredMethods, methodToDef(enclPkg)) val fields = mergeMap(c, c.getFields, c.getDeclaredFields, fieldToDef(enclPkg)) val constructors = mergeMap(c, c.getConstructors, c.getDeclaredConstructors, constructorToDef(enclPkg)) - val classes = merge[Class[_]](c, c.getClasses, c.getDeclaredClasses, toDefinitions, (_: Seq[Class[_]]).partition(isStatic), _.getEnclosingClass != c) + val classes = merge[Class[_]](c, c.getClasses, c.getDeclaredClasses, toDefinitions(cmap), (_: Seq[Class[_]]).partition(isStatic), _.getEnclosingClass != c) val all = (methods ++ fields ++ constructors ++ classes) val parentTypes = parents(c) val instanceStructure = new api.Structure(lzy(parentTypes.toArray), lzy(all.declared.toArray), lzy(all.inherited.toArray)) - def static = new api.Structure(emptyTpeArray, lzy(all.staticDeclared.toArray), lzy(all.staticInherited.toArray)) - val staticStructure = if(all.staticDeclared.isEmpty && all.staticInherited.isEmpty) None else Some(static) + val staticStructure = new api.Structure(emptyTpeArray, lzy(all.staticDeclared.toArray), lzy(all.staticInherited.toArray)) (staticStructure, instanceStructure) } def lzy[T <: AnyRef](t: => T): xsbti.api.Lazy[T] = xsbti.SafeLazy(t) diff --git a/sbt/src/sbt-test/java/basic/src/main/java/test/O2.java b/sbt/src/sbt-test/java/basic/src/main/java/test/O2.java new file mode 100644 index 000000000..2344e9b36 --- /dev/null +++ b/sbt/src/sbt-test/java/basic/src/main/java/test/O2.java @@ -0,0 +1,10 @@ +package test; + +public class O2 extends Outer { + public static class O3 extends O2 {} + public static class O4 extends Outer {} + public class O5 extends O4 {} + public class O6 extends O2 {} + public class O7 extends O5 {} +} + diff --git a/sbt/src/sbt-test/java/basic/src/main/java/test/Outer.java b/sbt/src/sbt-test/java/basic/src/main/java/test/Outer.java new file mode 100644 index 000000000..52a1acd58 --- /dev/null +++ b/sbt/src/sbt-test/java/basic/src/main/java/test/Outer.java @@ -0,0 +1,8 @@ +package test; + +public class Outer { + public class Inner extends Outer { + public class Inner2 extends Inner {} + public class InnerB extends Outer {} + } +}