From c2304b512f9ceca8cfb34446e4986128e63669a7 Mon Sep 17 00:00:00 2001 From: Eugene Vigdorchik Date: Fri, 20 Jan 2012 17:31:36 +0400 Subject: [PATCH 1/5] Add SourcePosition to setting. --- main/Build.scala | 8 ++++++-- main/Project.scala | 22 ++++++++++++++++++---- util/collection/Settings.scala | 31 ++++++++++++++++++++++--------- 3 files changed, 46 insertions(+), 15 deletions(-) diff --git a/main/Build.scala b/main/Build.scala index d985a70f7..c3c26bce6 100644 --- a/main/Build.scala +++ b/main/Build.scala @@ -8,8 +8,9 @@ package sbt import compiler.{Eval, EvalImports} import complete.DefaultParsers.validID import Compiler.Compilers - import Project.{ScopedKey, Setting} import Keys.{globalBaseDirectory, globalPluginsDirectory, globalSettingsDirectory, stagingDirectory, Streams} + import Project.{ScopedKey, Setting, SourceCoord} + import Keys.{globalBaseDirectory, Streams} import Scope.GlobalScope import scala.annotation.tailrec @@ -137,7 +138,10 @@ object EvaluateConfigurations } catch { case e: sbt.compiler.EvalException => throw new MessageOnlyException(e.getMessage) } - loader => result.getValue(loader).asInstanceOf[Project.SettingsDefinition].settings + loader => { + val coord = SourceCoord(name, line + 1) + result.getValue(loader).asInstanceOf[Project.SettingsDefinition].settings map (_ setPos coord) + } } private[this] def isSpace = (c: Char) => Character isWhitespace c private[this] def fstS(f: String => Boolean): ((String,Int)) => Boolean = { case (s,i) => f(s) } diff --git a/main/Project.scala b/main/Project.scala index b87de657f..3205a41c2 100755 --- a/main/Project.scala +++ b/main/Project.scala @@ -267,20 +267,34 @@ object Project extends Init[Scope] with ProjectExtra val data = scopedKeyData(structure, scope, key) map {_.description} getOrElse {"No entry for key."} val description = key.description match { case Some(desc) => "Description:\n\t" + desc + "\n"; case None => "" } - val definedIn = structure.data.definingScope(scope, key) match { + + val providedBy = structure.data.definingScope(scope, key) match { case Some(sc) => "Provided by:\n\t" + Scope.display(sc, key.label) + "\n" case None => "" } - val cMap = flattenLocals(compiled(structure.settings, actual)(structure.delegates, structure.scopeLocal, display)) + val comp = compiled(structure.settings, actual)(structure.delegates, structure.scopeLocal, display) + val definedAt = comp get scoped map { c => + if (c.settings forall (_.pos ne NoPosition)) { + def fmt(s: Setting[_]) = s.pos match { + case SourceCoord(fileName, line) => fileName + ":" + line + } + "Defined at:" + (c.settings map fmt mkString ("\n\t", "\n\t", "\n")) + } else "" + } getOrElse "" + + + val cMap = flattenLocals(comp) val related = cMap.keys.filter(k => k.key == key && k.scope != scope) val depends = cMap.get(scoped) match { case Some(c) => c.dependencies.toSet; case None => Set.empty } + val reverse = reverseDependencies(cMap, scoped) def printScopes(label: String, scopes: Iterable[ScopedKey[_]]) = if(scopes.isEmpty) "" else scopes.map(display.apply).mkString(label + ":\n\t", "\n\t", "\n") data + "\n" + description + - definedIn + + providedBy + + definedAt + printScopes("Dependencies", depends) + printScopes("Reverse dependencies", reverse) + printScopes("Delegates", delegates(structure, scope, key)) + @@ -332,7 +346,7 @@ object Project extends Init[Scope] with ProjectExtra { val akey = setting.key.key val global = ScopedKey(Global, akey) - val globalSetting = resolve( Project.setting(global, setting.init) ) + val globalSetting = resolve( Project.setting(global, setting.init, setting.pos) ) globalSetting ++ allDefs.flatMap { d => if(d.key == akey) Seq( SettingKey(akey) in d.scope <<= global) diff --git a/util/collection/Settings.scala b/util/collection/Settings.scala index 4111c9082..fe97313f2 100644 --- a/util/collection/Settings.scala +++ b/util/collection/Settings.scala @@ -58,10 +58,10 @@ trait Init[Scope] type ScopeLocal = ScopedKey[_] => Seq[Setting[_]] type MapConstant = ScopedKey ~> Option - def setting[T](key: ScopedKey[T], init: Initialize[T]): Setting[T] = new Setting[T](key, init) + def setting[T](key: ScopedKey[T], init: Initialize[T], pos: SourcePosition = NoPosition): Setting[T] = new Setting[T](key, init, pos) def value[T](value: => T): Initialize[T] = new Value(value _) def optional[T,U](i: Initialize[T])(f: Option[T] => U): Initialize[U] = new Optional(Some(i), f) - def update[T](key: ScopedKey[T])(f: T => T): Setting[T] = new Setting[T](key, app(key :^: KNil)(hl => f(hl.head))) + def update[T](key: ScopedKey[T])(f: T => T): Setting[T] = new Setting[T](key, app(key :^: KNil)(hl => f(hl.head)), NoPosition) def bind[S,T](in: Initialize[S])(f: S => Initialize[T]): Initialize[T] = new Bind(f, in) def app[HL <: HList, T](inputs: KList[Initialize, HL])(f: HL => T): Initialize[T] = new Apply(f, inputs) def uniform[S,T](inputs: Seq[Initialize[S]])(f: Seq[S] => T): Initialize[T] = new Uniform(f, inputs) @@ -245,19 +245,32 @@ trait Init[Scope] def settings: Seq[Setting[_]] } final class SettingList(val settings: Seq[Setting[_]]) extends SettingsDefinition - final class Setting[T](val key: ScopedKey[T], val init: Initialize[T]) extends SettingsDefinition + final class Setting[T](val key: ScopedKey[T], val init: Initialize[T], val pos: SourcePosition) extends SettingsDefinition { def settings = this :: Nil def definitive: Boolean = !init.dependencies.contains(key) def dependencies: Seq[ScopedKey[_]] = remove(init.dependencies, key) - def mapReferenced(g: MapScoped): Setting[T] = new Setting(key, init mapReferenced g) - def validateReferenced(g: ValidateRef): Either[Seq[Undefined], Setting[T]] = (init validateReferenced g).right.map(newI => new Setting(key, newI)) - def mapKey(g: MapScoped): Setting[T] = new Setting(g(key), init) - def mapInit(f: (ScopedKey[T], T) => T): Setting[T] = new Setting(key, init(t => f(key,t))) - def mapConstant(g: MapConstant): Setting[T] = new Setting(key, init mapConstant g) - override def toString = "setting(" + key + ")" + def mapReferenced(g: MapScoped): Setting[T] = new Setting(key, init mapReferenced g, pos) + def validateReferenced(g: ValidateRef): Either[Seq[Undefined], Setting[T]] = (init validateReferenced g).right.map(newI => new Setting(key, newI, pos)) + def mapKey(g: MapScoped): Setting[T] = new Setting(g(key), init, pos) + def mapInit(f: (ScopedKey[T], T) => T): Setting[T] = new Setting(key, init(t => f(key,t)), pos) + def mapConstant(g: MapConstant): Setting[T] = new Setting(key, init mapConstant g, pos) + def setPos(pos: SourceCoord) = new Setting(key, init, pos) + override def toString = "setting(" + key + ") at " + pos } + trait SourcePosition { + def fileName: String + def line: Int + } + + case object NoPosition extends SourcePosition { + override def fileName = throw new UnsupportedOperationException("NoPosition") + override def line = throw new UnsupportedOperationException("NoPosition") + } + + case class SourceCoord(fileName: String, line: Int) extends SourcePosition + // mainly for reducing generated class count private[this] def validateReferencedT(g: ValidateRef) = new (Initialize ~> ValidatedInit) { def apply[T](i: Initialize[T]) = i validateReferenced g } From 633f4736b332c150d2a0256fb580d8d25489b391 Mon Sep 17 00:00:00 2001 From: Eugene Vigdorchik Date: Fri, 20 Jan 2012 17:31:36 +0400 Subject: [PATCH 2/5] Add SourcePosition to setting. --- main/Build.scala | 8 ++++++-- main/Project.scala | 22 ++++++++++++++++++---- util/collection/Settings.scala | 31 ++++++++++++++++++++++--------- 3 files changed, 46 insertions(+), 15 deletions(-) diff --git a/main/Build.scala b/main/Build.scala index d985a70f7..c3c26bce6 100644 --- a/main/Build.scala +++ b/main/Build.scala @@ -8,8 +8,9 @@ package sbt import compiler.{Eval, EvalImports} import complete.DefaultParsers.validID import Compiler.Compilers - import Project.{ScopedKey, Setting} import Keys.{globalBaseDirectory, globalPluginsDirectory, globalSettingsDirectory, stagingDirectory, Streams} + import Project.{ScopedKey, Setting, SourceCoord} + import Keys.{globalBaseDirectory, Streams} import Scope.GlobalScope import scala.annotation.tailrec @@ -137,7 +138,10 @@ object EvaluateConfigurations } catch { case e: sbt.compiler.EvalException => throw new MessageOnlyException(e.getMessage) } - loader => result.getValue(loader).asInstanceOf[Project.SettingsDefinition].settings + loader => { + val coord = SourceCoord(name, line + 1) + result.getValue(loader).asInstanceOf[Project.SettingsDefinition].settings map (_ setPos coord) + } } private[this] def isSpace = (c: Char) => Character isWhitespace c private[this] def fstS(f: String => Boolean): ((String,Int)) => Boolean = { case (s,i) => f(s) } diff --git a/main/Project.scala b/main/Project.scala index b87de657f..3205a41c2 100755 --- a/main/Project.scala +++ b/main/Project.scala @@ -267,20 +267,34 @@ object Project extends Init[Scope] with ProjectExtra val data = scopedKeyData(structure, scope, key) map {_.description} getOrElse {"No entry for key."} val description = key.description match { case Some(desc) => "Description:\n\t" + desc + "\n"; case None => "" } - val definedIn = structure.data.definingScope(scope, key) match { + + val providedBy = structure.data.definingScope(scope, key) match { case Some(sc) => "Provided by:\n\t" + Scope.display(sc, key.label) + "\n" case None => "" } - val cMap = flattenLocals(compiled(structure.settings, actual)(structure.delegates, structure.scopeLocal, display)) + val comp = compiled(structure.settings, actual)(structure.delegates, structure.scopeLocal, display) + val definedAt = comp get scoped map { c => + if (c.settings forall (_.pos ne NoPosition)) { + def fmt(s: Setting[_]) = s.pos match { + case SourceCoord(fileName, line) => fileName + ":" + line + } + "Defined at:" + (c.settings map fmt mkString ("\n\t", "\n\t", "\n")) + } else "" + } getOrElse "" + + + val cMap = flattenLocals(comp) val related = cMap.keys.filter(k => k.key == key && k.scope != scope) val depends = cMap.get(scoped) match { case Some(c) => c.dependencies.toSet; case None => Set.empty } + val reverse = reverseDependencies(cMap, scoped) def printScopes(label: String, scopes: Iterable[ScopedKey[_]]) = if(scopes.isEmpty) "" else scopes.map(display.apply).mkString(label + ":\n\t", "\n\t", "\n") data + "\n" + description + - definedIn + + providedBy + + definedAt + printScopes("Dependencies", depends) + printScopes("Reverse dependencies", reverse) + printScopes("Delegates", delegates(structure, scope, key)) + @@ -332,7 +346,7 @@ object Project extends Init[Scope] with ProjectExtra { val akey = setting.key.key val global = ScopedKey(Global, akey) - val globalSetting = resolve( Project.setting(global, setting.init) ) + val globalSetting = resolve( Project.setting(global, setting.init, setting.pos) ) globalSetting ++ allDefs.flatMap { d => if(d.key == akey) Seq( SettingKey(akey) in d.scope <<= global) diff --git a/util/collection/Settings.scala b/util/collection/Settings.scala index 4111c9082..fe97313f2 100644 --- a/util/collection/Settings.scala +++ b/util/collection/Settings.scala @@ -58,10 +58,10 @@ trait Init[Scope] type ScopeLocal = ScopedKey[_] => Seq[Setting[_]] type MapConstant = ScopedKey ~> Option - def setting[T](key: ScopedKey[T], init: Initialize[T]): Setting[T] = new Setting[T](key, init) + def setting[T](key: ScopedKey[T], init: Initialize[T], pos: SourcePosition = NoPosition): Setting[T] = new Setting[T](key, init, pos) def value[T](value: => T): Initialize[T] = new Value(value _) def optional[T,U](i: Initialize[T])(f: Option[T] => U): Initialize[U] = new Optional(Some(i), f) - def update[T](key: ScopedKey[T])(f: T => T): Setting[T] = new Setting[T](key, app(key :^: KNil)(hl => f(hl.head))) + def update[T](key: ScopedKey[T])(f: T => T): Setting[T] = new Setting[T](key, app(key :^: KNil)(hl => f(hl.head)), NoPosition) def bind[S,T](in: Initialize[S])(f: S => Initialize[T]): Initialize[T] = new Bind(f, in) def app[HL <: HList, T](inputs: KList[Initialize, HL])(f: HL => T): Initialize[T] = new Apply(f, inputs) def uniform[S,T](inputs: Seq[Initialize[S]])(f: Seq[S] => T): Initialize[T] = new Uniform(f, inputs) @@ -245,19 +245,32 @@ trait Init[Scope] def settings: Seq[Setting[_]] } final class SettingList(val settings: Seq[Setting[_]]) extends SettingsDefinition - final class Setting[T](val key: ScopedKey[T], val init: Initialize[T]) extends SettingsDefinition + final class Setting[T](val key: ScopedKey[T], val init: Initialize[T], val pos: SourcePosition) extends SettingsDefinition { def settings = this :: Nil def definitive: Boolean = !init.dependencies.contains(key) def dependencies: Seq[ScopedKey[_]] = remove(init.dependencies, key) - def mapReferenced(g: MapScoped): Setting[T] = new Setting(key, init mapReferenced g) - def validateReferenced(g: ValidateRef): Either[Seq[Undefined], Setting[T]] = (init validateReferenced g).right.map(newI => new Setting(key, newI)) - def mapKey(g: MapScoped): Setting[T] = new Setting(g(key), init) - def mapInit(f: (ScopedKey[T], T) => T): Setting[T] = new Setting(key, init(t => f(key,t))) - def mapConstant(g: MapConstant): Setting[T] = new Setting(key, init mapConstant g) - override def toString = "setting(" + key + ")" + def mapReferenced(g: MapScoped): Setting[T] = new Setting(key, init mapReferenced g, pos) + def validateReferenced(g: ValidateRef): Either[Seq[Undefined], Setting[T]] = (init validateReferenced g).right.map(newI => new Setting(key, newI, pos)) + def mapKey(g: MapScoped): Setting[T] = new Setting(g(key), init, pos) + def mapInit(f: (ScopedKey[T], T) => T): Setting[T] = new Setting(key, init(t => f(key,t)), pos) + def mapConstant(g: MapConstant): Setting[T] = new Setting(key, init mapConstant g, pos) + def setPos(pos: SourceCoord) = new Setting(key, init, pos) + override def toString = "setting(" + key + ") at " + pos } + trait SourcePosition { + def fileName: String + def line: Int + } + + case object NoPosition extends SourcePosition { + override def fileName = throw new UnsupportedOperationException("NoPosition") + override def line = throw new UnsupportedOperationException("NoPosition") + } + + case class SourceCoord(fileName: String, line: Int) extends SourcePosition + // mainly for reducing generated class count private[this] def validateReferencedT(g: ValidateRef) = new (Initialize ~> ValidatedInit) { def apply[T](i: Initialize[T]) = i validateReferenced g } From f9da9e7defd411c8b5d1f560d6da7a67873d7e39 Mon Sep 17 00:00:00 2001 From: Eugene Vigdorchik Date: Mon, 23 Jan 2012 17:42:50 +0400 Subject: [PATCH 3/5] Display sourcepos info when at least 1 pos known. --- main/Project.scala | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/main/Project.scala b/main/Project.scala index 3205a41c2..13063de78 100755 --- a/main/Project.scala +++ b/main/Project.scala @@ -274,11 +274,12 @@ object Project extends Init[Scope] with ProjectExtra } val comp = compiled(structure.settings, actual)(structure.delegates, structure.scopeLocal, display) val definedAt = comp get scoped map { c => - if (c.settings forall (_.pos ne NoPosition)) { + if (c.settings exists (_.pos ne NoPosition)) { + val header = if (c.settings forall (_.pos ne NoPosition)) "Defined at:" else "Some of the definition places:" def fmt(s: Setting[_]) = s.pos match { case SourceCoord(fileName, line) => fileName + ":" + line } - "Defined at:" + (c.settings map fmt mkString ("\n\t", "\n\t", "\n")) + header + (c.settings filter (_.pos ne NoPosition) map fmt mkString ("\n\t", "\n\t", "\n")) } else "" } getOrElse "" From 6d0c2c8d33b67f4d81039c3d5553f03b3b2cf6c6 Mon Sep 17 00:00:00 2001 From: Eugene Vigdorchik Date: Tue, 24 Jan 2012 13:32:21 +0400 Subject: [PATCH 4/5] Change SourcePosition definition + minor cleanup. --- main/Project.scala | 8 +++++--- util/collection/Settings.scala | 12 ++---------- 2 files changed, 7 insertions(+), 13 deletions(-) diff --git a/main/Project.scala b/main/Project.scala index 13063de78..d4d7d94bb 100755 --- a/main/Project.scala +++ b/main/Project.scala @@ -274,12 +274,14 @@ object Project extends Init[Scope] with ProjectExtra } val comp = compiled(structure.settings, actual)(structure.delegates, structure.scopeLocal, display) val definedAt = comp get scoped map { c => - if (c.settings exists (_.pos ne NoPosition)) { - val header = if (c.settings forall (_.pos ne NoPosition)) "Defined at:" else "Some of the definition places:" + val posDefined = c.settings filter (_.pos ne NoPosition) + if (posDefined.size > 0) { + val header = if (posDefined.size == c.settings.size) "Defined at:" else + "Some of the defining occurrences:" def fmt(s: Setting[_]) = s.pos match { case SourceCoord(fileName, line) => fileName + ":" + line } - header + (c.settings filter (_.pos ne NoPosition) map fmt mkString ("\n\t", "\n\t", "\n")) + header + (posDefined map fmt mkString ("\n\t", "\n\t", "\n")) } else "" } getOrElse "" diff --git a/util/collection/Settings.scala b/util/collection/Settings.scala index fe97313f2..1c5634c1c 100644 --- a/util/collection/Settings.scala +++ b/util/collection/Settings.scala @@ -259,16 +259,8 @@ trait Init[Scope] override def toString = "setting(" + key + ") at " + pos } - trait SourcePosition { - def fileName: String - def line: Int - } - - case object NoPosition extends SourcePosition { - override def fileName = throw new UnsupportedOperationException("NoPosition") - override def line = throw new UnsupportedOperationException("NoPosition") - } - + sealed trait SourcePosition + case object NoPosition extends SourcePosition case class SourceCoord(fileName: String, line: Int) extends SourcePosition // mainly for reducing generated class count From 1c63847a3dd2db2067ad5883173daed0233e6873 Mon Sep 17 00:00:00 2001 From: Eugene Vigdorchik Date: Fri, 27 Jan 2012 17:51:13 +0400 Subject: [PATCH 5/5] More cleanup. --- main/Build.scala | 2 +- main/Project.scala | 11 ++++++----- util/collection/Settings.scala | 4 ++-- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/main/Build.scala b/main/Build.scala index c3c26bce6..6ab7bb043 100644 --- a/main/Build.scala +++ b/main/Build.scala @@ -140,7 +140,7 @@ object EvaluateConfigurations } loader => { val coord = SourceCoord(name, line + 1) - result.getValue(loader).asInstanceOf[Project.SettingsDefinition].settings map (_ setPos coord) + result.getValue(loader).asInstanceOf[Project.SettingsDefinition].settings map (_ withPos coord) } } private[this] def isSpace = (c: Char) => Character isWhitespace c diff --git a/main/Project.scala b/main/Project.scala index d4d7d94bb..db053c732 100755 --- a/main/Project.scala +++ b/main/Project.scala @@ -274,14 +274,15 @@ object Project extends Init[Scope] with ProjectExtra } val comp = compiled(structure.settings, actual)(structure.delegates, structure.scopeLocal, display) val definedAt = comp get scoped map { c => - val posDefined = c.settings filter (_.pos ne NoPosition) + def fmt(s: Setting[_]) = s.pos match { + case SourceCoord(fileName, line) => Some(fileName + ":" + line) + case NoPosition => None + } + val posDefined = c.settings.map(fmt).flatten if (posDefined.size > 0) { val header = if (posDefined.size == c.settings.size) "Defined at:" else "Some of the defining occurrences:" - def fmt(s: Setting[_]) = s.pos match { - case SourceCoord(fileName, line) => fileName + ":" + line - } - header + (posDefined map fmt mkString ("\n\t", "\n\t", "\n")) + header + (posDefined mkString ("\n\t", "\n\t", "\n")) } else "" } getOrElse "" diff --git a/util/collection/Settings.scala b/util/collection/Settings.scala index 1c5634c1c..01c3d5e2f 100644 --- a/util/collection/Settings.scala +++ b/util/collection/Settings.scala @@ -255,13 +255,13 @@ trait Init[Scope] def mapKey(g: MapScoped): Setting[T] = new Setting(g(key), init, pos) def mapInit(f: (ScopedKey[T], T) => T): Setting[T] = new Setting(key, init(t => f(key,t)), pos) def mapConstant(g: MapConstant): Setting[T] = new Setting(key, init mapConstant g, pos) - def setPos(pos: SourceCoord) = new Setting(key, init, pos) + def withPos(pos: SourceCoord) = new Setting(key, init, pos) override def toString = "setting(" + key + ") at " + pos } sealed trait SourcePosition case object NoPosition extends SourcePosition - case class SourceCoord(fileName: String, line: Int) extends SourcePosition + final case class SourceCoord(fileName: String, line: Int) extends SourcePosition // mainly for reducing generated class count private[this] def validateReferencedT(g: ValidateRef) =