Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 1 addition & 1 deletion src/compiler/scala/tools/nsc/Global.scala
Original file line number Diff line number Diff line change
Expand Up @@ -1588,7 +1588,7 @@ class Global(var currentSettings: Settings, reporter0: Reporter)
if (settings.browse.containsPhase(globalPhase))
treeBrowser.browse(phase.name, units)

if ((settings.Yvalidatepos containsPhase globalPhase) && !reporter.hasErrors)
if (!reporter.hasErrors && settings.Yvalidatepos.containsPhase(globalPhase))
currentRun.units.foreach(unit => validatePositions(unit.body))

// move the pointer
Expand Down
2 changes: 1 addition & 1 deletion src/compiler/scala/tools/nsc/reporters/StoreReporter.scala
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,6 @@ class StoreReporter(val settings: Settings) extends FilteringReporter {
}
object StoreReporter {
case class Info(pos: Position, msg: String, severity: Severity, actions: List[CodeAction]) {
override def toString: String = s"pos: $pos $msg $severity${if (actions.isEmpty) "" else " " + actions}"
override def toString: String = s"pos: $pos $msg $severity${if (actions.isEmpty) "" else actions}"
}
}
62 changes: 25 additions & 37 deletions src/compiler/scala/tools/nsc/typechecker/TypeDiagnostics.scala
Original file line number Diff line number Diff line change
Expand Up @@ -86,12 +86,6 @@ trait TypeDiagnostics extends splain.SplainDiagnostics {
prefix + name.decode
}

// Bind of pattern var was `x @ _`
private def nowarn(t: Tree) = t.hasAttachment[NoWarnAttachment.type]

// ValDef was a PatVarDef `val P(x) = ???`
private def wasPatVarDef(t: Tree) = t.hasAttachment[PatVarDefAttachment.type]

/** Does the positioned line assigned to t1 precede that of t2?
*/
def posPrecedes(p1: Position, p2: Position) = p1.isDefined && p2.isDefined && p1.line < p2.line
Expand Down Expand Up @@ -499,26 +493,26 @@ trait TypeDiagnostics extends splain.SplainDiagnostics {
val ignoreNames: Set[TermName] = Set(
"readResolve", "readObject", "writeObject", "writeReplace"
).map(TermName(_))

// Bind of pattern var was `x @ _`; also used for wildcard, e.g. `_ <- e`
private def nowarn(tree: Bind): Boolean = tree.hasAttachment[NoWarnAttachment.type]
private def nowarn(tree: ValDef): Boolean = tree.hasAttachment[NoWarnAttachment.type]

// ValDef was a PatVarDef `val P(x) = ???`
private def wasPatVarDef(tree: ValDef): Boolean = tree.hasAttachment[PatVarDefAttachment.type]
}

class UnusedPrivates extends Traverser {
import UnusedPrivates.ignoreNames
import UnusedPrivates.{ignoreNames, nowarn, wasPatVarDef}
def isEffectivelyPrivate(sym: Symbol): Boolean = false
val defnTrees = ListBuffer.empty[MemberDef]
val targets = mutable.Set.empty[Symbol]
val setVars = mutable.Set.empty[Symbol]
val treeTypes = mutable.Set.empty[Type]
val params = mutable.Set.empty[Symbol]
val patvars = mutable.Set.empty[Symbol]
val aliases = mutable.Map.empty[Symbol, Symbol]

def aliasOf(sym: Symbol): Symbol = aliases.getOrElse(sym, sym)
def followVarAlias(tree: Tree): Symbol =
tree.attachments.get[VarAlias] match {
case Some(VarAlias(original)) => followVarAlias(original)
case _ => tree.symbol
}
def recordReference(sym: Symbol): Unit = targets.addOne(aliasOf(sym))
val patvars = ListBuffer.empty[Tree /*Bind|ValDef*/]

def recordReference(sym: Symbol): Unit = targets.addOne(sym)

def qualifiesTerm(sym: Symbol) = (
(sym.isModule || sym.isMethod || sym.isPrivateLocal || sym.isLocalToBlock || isEffectivelyPrivate(sym))
Expand All @@ -534,6 +528,7 @@ trait TypeDiagnostics extends splain.SplainDiagnostics {
&& (sym.isTerm && qualifiesTerm(sym) || sym.isType && qualifiesType(sym))
)
def isExisting(sym: Symbol) = sym != null && sym.exists
def addPatVar(t: Tree) = patvars += t

// so trivial that it never consumes params
def isTrivial(rhs: Tree): Boolean =
Expand All @@ -551,11 +546,7 @@ trait TypeDiagnostics extends splain.SplainDiagnostics {
t match {
case t: ValDef =>
if (wasPatVarDef(t)) {
if (settings.warnUnusedPatVars && !nowarn(t))
if (t.hasAttachment[VarAlias])
aliases += sym -> followVarAlias(t)
else
patvars += sym
if (settings.warnUnusedPatVars && !nowarn(t)) addPatVar(t)
}
else defnTrees += m
case DefDef(_, _, _, vparamss, _, rhs) if !sym.isAbstract && !sym.isDeprecated && !sym.isMacro =>
Expand Down Expand Up @@ -589,11 +580,7 @@ trait TypeDiagnostics extends splain.SplainDiagnostics {
case _ =>
}
pat.foreach {
case b @ Bind(n, _) if !nowarn(b) && n != nme.DEFAULT_CASE =>
if (b.hasAttachment[VarAlias])
aliases += b.symbol -> followVarAlias(b)
else
patvars += b.symbol
case b @ Bind(n, _) if !nowarn(b) && n != nme.DEFAULT_CASE => addPatVar(b)
case _ =>
}
case _: RefTree => if (isExisting(sym) && !currentOwner.hasTransOwner(sym)) recordReference(sym)
Expand All @@ -602,13 +589,9 @@ trait TypeDiagnostics extends splain.SplainDiagnostics {
for (p <- ps)
if (wasPatVarDef(p)) {
if (settings.warnUnusedPatVars && !nowarn(p))
if (p.hasAttachment[VarAlias])
aliases += p.symbol -> followVarAlias(p)
else
patvars += p.symbol
addPatVar(p)
}
else if (settings.warnUnusedParams && !nowarn(p) && !p.symbol.isSynthetic)
params += p.symbol
else if (settings.warnUnusedParams && !nowarn(p) && !p.symbol.isSynthetic) params += p.symbol
case Literal(_) =>
t.attachments.get[OriginalTreeAttachment].foreach(ota => traverse(ota.original))
case tt: TypeTree =>
Expand Down Expand Up @@ -705,7 +688,13 @@ trait TypeDiagnostics extends splain.SplainDiagnostics {
}
def unusedParams = params.iterator.filter(isUnusedParam)
def inDefinedAt(p: Symbol) = p.owner.isMethod && p.owner.name == nme.isDefinedAt && p.owner.owner.isAnonymousFunction
def unusedPatVars = patvars.iterator.filter(p => isUnusedTerm(p) && !inDefinedAt(p))
def unusedPatVars = {
// in elaboration of for comprehensions, patterns are duplicated; track a patvar by its start position; "original" has a range pos
val all = patvars.filterInPlace(_.pos.isDefined)
val byPos = all.groupBy(_.pos.start)
def isUnusedPatVar(t: Tree): Boolean = byPos(t.pos.start).forall(p => !targets(p.symbol))
all.iterator.filter(p => p.pos.isOpaqueRange && isUnusedTerm(p.symbol) && isUnusedPatVar(p) && !inDefinedAt(p.symbol))
}
}

class checkUnused(typer: Typer) {
Expand Down Expand Up @@ -820,10 +809,9 @@ trait TypeDiagnostics extends splain.SplainDiagnostics {
emitUnusedWarning(v.pos, s"local var ${v.nameString} in ${v.owner} ${varAdvice(v)}", WarningCategory.UnusedPrivates, v)
}
}
if (settings.warnUnusedPatVars) {
if (settings.warnUnusedPatVars)
for (v <- unusedPrivates.unusedPatVars)
emitUnusedWarning(v.pos, s"pattern var ${v.name} in ${v.owner} is never used", WarningCategory.UnusedPatVars, v)
}
emitUnusedWarning(v.pos, s"pattern var ${v.symbol.name} in ${v.symbol.owner} is never used", WarningCategory.UnusedPatVars, v.symbol)
if (settings.warnUnusedParams) {
// don't warn unused args of overriding methods (or methods matching in self-type)
def isImplementation(m: Symbol): Boolean = m.isMethod && {
Expand Down
189 changes: 91 additions & 98 deletions src/reflect/scala/reflect/internal/Positions.scala
Original file line number Diff line number Diff line change
Expand Up @@ -125,51 +125,50 @@ trait Positions extends api.Positions { self: SymbolTable =>
if (useOffsetPositions) Position.offset(source, point)
else Position.range(source, start, point, end)


abstract class ChildSolidDescendantsCollector extends Traverser {
// don't traverse annotations
override def traverseModifiers(mods: Modifiers): Unit = ()

override def traverse(tree: Tree): Unit =
if (tree ne EmptyTree) {
if (tree ne EmptyTree)
if (tree.pos.isTransparent) super.traverse(tree)
else {
traverseSolidChild(tree)
}
}
def traverseSolidChild(t: Tree): Unit
def apply(t: Tree): Unit = super.traverse(t)
}
else traverseSolidChild(tree)

private[this] def reportTree(prefix: String, tree: Tree): Unit = {
val source = if (tree.pos.isDefined) tree.pos.source else ""
inform("== " + prefix + " tree [" + tree.id + "] of type " + tree.productPrefix + " at " + tree.pos.show + source)
inform("")
inform(treeStatus(tree))
inform("")
}
def traverseSolidChild(t: Tree): Unit

private[this] def positionError(topTree: Tree, msg: String)(body: => Unit): Unit = {
inform("======= Position error\n" + msg)
body
inform("\nWhile validating #" + topTree.id)
inform(treeStatus(topTree))
inform("\nChildren:")
topTree.children foreach (t => inform(" " + treeStatus(t, topTree)))
inform("=======")
throw new ValidateException(msg)
def apply(t: Tree): Unit = super.traverse(t)
}

private[this] val posStartOrdering: Ordering[Tree] = new Ordering[Tree] {
private val posStartOrdering: Ordering[Tree] = new Ordering[Tree] {
override def compare(x: Tree, y: Tree): Int = {
@inline def posOf(t: Tree): Int = {
def posOf(t: Tree): Int = {
val pos = t.pos
if (pos eq NoPosition) Int.MinValue else pos.start
}
Integer.compare(posOf(x), posOf(y))
}
}

def validatePositions(tree: Tree): Unit = if (!useOffsetPositions) {
def reportTree(prefix: String, tree: Tree): Unit = {
val source = if (tree.pos.isDefined) tree.pos.source else ""
inform("== " + prefix + " tree [" + tree.id + "] of type " + tree.productPrefix + " at " + tree.pos.show + source)
inform("")
inform(treeStatus(tree))
inform("")
}

def positionError(topTree: Tree, msg: String)(body: => Unit): Unit = {
inform("======= Position error\n" + msg)
body
inform("\nWhile validating #" + topTree.id)
inform(treeStatus(topTree))
inform("\nChildren:")
topTree.children foreach (t => inform(" " + treeStatus(t, topTree)))
inform("=======")
throw new ValidateException(msg)
}

object worker {
val trace = settings.Yposdebug.value && settings.verbose.value
val topTree = tree
Expand Down Expand Up @@ -210,73 +209,70 @@ trait Positions extends api.Positions { self: SymbolTable =>
}
}

def loop(tree: Tree, encltree: Tree): Unit = {
if (!tree.isEmpty && tree.canHaveAttrs) {
val treePos = tree.pos
if (trace)
inform("[%10s] %s".format("validate", treeStatus(tree, encltree)))

if (!treePos.isDefined)
positionError(topTree, "Unpositioned tree #" + tree.id) {
inform("%15s %s".format("unpositioned", treeStatus(tree, encltree)))
inform("%15s %s".format("enclosing", treeStatus(encltree)))
encltree.children foreach (t => inform("%15s %s".format("sibling", treeStatus(t, encltree))))
}
def loop(tree: Tree, encltree: Tree): Unit = if (!tree.isEmpty && tree.canHaveAttrs) {
val treePos = tree.pos
if (trace)
inform(f"[${"validate"}%10s] ${treeStatus(tree, encltree)}")

solidChildrenCollector(tree)
val numChildren = solidChildrenCollector.collectedSize
if (!treePos.isDefined)
positionError(topTree, s"Unpositioned tree #${tree.id}") {
inform("%15s %s".format("unpositioned", treeStatus(tree, encltree)))
inform("%15s %s".format("enclosing", treeStatus(encltree)))
encltree.children foreach (t => inform("%15s %s".format("sibling", treeStatus(t, encltree))))
}

if (treePos.isRange) {
val enclPos = encltree.pos
if (!enclPos.isRange)
positionError(topTree, "Synthetic tree [" + encltree.id + "] contains nonsynthetic tree [" + tree.id + "]") {
reportTree("Enclosing", encltree)
reportTree("Enclosed", tree)
}
if (!(enclPos includes treePos))
positionError(topTree, "Enclosing tree [" + encltree.id + "] does not include tree [" + tree.id + "]") {
reportTree("Enclosing", encltree)
reportTree("Enclosed", tree)
}
solidChildrenCollector(tree)
val numChildren = solidChildrenCollector.collectedSize

if (numChildren > 1) {
val childSolidDescendants = solidChildrenCollector.sortedArray
var t1 = childSolidDescendants(0)
var t1Pos = t1.pos
var i = 1
while (i < numChildren) {
val t2 = childSolidDescendants(i)
val t2Pos = t2.pos
if (t1Pos.overlaps(t2Pos)) {
positionError(topTree, "Overlapping trees") {
reportTree("Ancestor", tree)
reportTree("First overlapping", t1)
reportTree("Second overlapping", t2)
}
}
//why only for range
if (t2Pos.isRange) {
t1 = t2
t1Pos = t2Pos
if (treePos.isRange) {
val enclPos = encltree.pos
if (!enclPos.isRange)
positionError(topTree, "Synthetic tree [" + encltree.id + "] contains nonsynthetic tree [" + tree.id + "]") {
reportTree("Enclosing", encltree)
reportTree("Enclosed", tree)
}
if (!enclPos.includes(treePos))
positionError(topTree, "Enclosing tree [" + encltree.id + "] does not include tree [" + tree.id + "]") {
reportTree("Enclosing", encltree)
reportTree("Enclosed", tree)
}

if (numChildren > 1) {
val childSolidDescendants = solidChildrenCollector.sortedArray
var t1 = childSolidDescendants(0)
var t1Pos = t1.pos
var i = 1
while (i < numChildren) {
val t2 = childSolidDescendants(i)
val t2Pos = t2.pos
if (t1Pos.overlaps(t2Pos)) {
positionError(topTree, "Overlapping trees") {
reportTree("Ancestor", tree)
reportTree("First overlapping", t1)
reportTree("Second overlapping", t2)
}
i += 1
}
if (t2Pos.isRange) { // only ranges overlap, so check ranges pairwise
t1 = t2
t1Pos = t2Pos
}
i += 1
}
}
if (numChildren > 0) {
if (numChildren == 1) {
val first = solidChildrenCollector.child(0)
solidChildrenCollector.clear()
loop(first, tree)
} else {
val snap = solidChildrenCollector.borrowArray
var i = 0
while (i < numChildren) {
loop(snap(i), tree)
i += 1
}
solidChildrenCollector.spareArray(snap)
}
if (numChildren > 0) {
if (numChildren == 1) {
val first = solidChildrenCollector.child(0)
solidChildrenCollector.clear()
loop(first, tree)
} else {
val snap = solidChildrenCollector.borrowArray
var i = 0
while (i < numChildren) {
loop(snap(i), tree)
i += 1
}
solidChildrenCollector.spareArray(snap)
}
}
}
Expand Down Expand Up @@ -396,23 +392,20 @@ trait Positions extends api.Positions { self: SymbolTable =>
/** Position a tree.
* This means: Set position of a node and position all its unpositioned children.
*/
def atPos[T <: Tree](pos: Position)(tree: T): T = {
def atPos[T <: Tree](pos: Position)(tree: T): tree.type = {
if (useOffsetPositions || !pos.isOpaqueRange) {
posAssigner.pos = pos
posAssigner.traverse(tree)
tree
}
else {
if (!tree.isEmpty && tree.canHaveAttrs && tree.pos == NoPosition) {
tree.setPos(pos)
tree.onlyChild match {
case EmptyTree =>
setChildrenPos(pos, tree)
case only =>
atPos(pos)(only)
}
else if (!tree.isEmpty && tree.canHaveAttrs && tree.pos == NoPosition) {
tree.setPos(pos)
tree.onlyChild match {
case EmptyTree =>
setChildrenPos(pos, tree)
case only =>
atPos(pos)(only)
}
tree
}
tree
}
}
3 changes: 0 additions & 3 deletions src/reflect/scala/reflect/internal/StdAttachments.scala
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,4 @@ trait StdAttachments {
case object DiscardedExpr extends PlainAttachment
/** Anonymous parameter of `if (_)` may be inferred as Boolean. */
case object BooleanParameterType extends PlainAttachment

/** This Bind tree was derived immediately from the given tree, for unused accounting. */
case class VarAlias(tree: Tree /*Bind | ValDef*/) extends PlainAttachment
}
Loading