Line content from diagnostic classes if available

This commit is contained in:
fkorotkov 2015-07-15 14:49:12 -04:00
parent 0504b162ff
commit 4c86117b79
3 changed files with 49 additions and 21 deletions

View File

@ -573,7 +573,7 @@ lazy val safeUnitTests = taskKey[Unit]("Known working tests (for both 2.10 and 2
lazy val safeProjects: ScopeFilter = ScopeFilter(
inProjects(mainSettingsProj, mainProj, ivyProj, completeProj,
actionsProj, classpathProj, collectionProj, compileIncrementalProj,
logProj, runProj, stdTaskProj),
logProj, runProj, stdTaskProj, compilerProj),
inConfigurations(Test)
)
lazy val otherUnitTests = taskKey[Unit]("Unit test other projects")

View File

@ -69,18 +69,37 @@ final class DiagnosticsReporter(reporter: Reporter) extends DiagnosticListener[J
def startPosition: Option[Long] = checkNoPos(d.getStartPosition)
def endPosition: Option[Long] = checkNoPos(d.getEndPosition)
override val offset: Maybe[Integer] = Logger.o2m(checkNoPos(d.getPosition) map { x => new Integer(x.toInt) })
// TODO - Is this pulling contents of the line correctly?
// Would be ok to just return null if this version of the JDK doesn't support grabbing
// source lines?
override def lineContent: String =
Option(d.getSource) match {
case Some(source: JavaFileObject) =>
(Option(source.getCharContent(true)), startPosition, endPosition) match {
case (Some(cc), Some(start), Some(end)) => cc.subSequence(start.toInt, end.toInt).toString
case _ => ""
override def lineContent: String = {
def getDiagnosticLine: Option[String] =
try {
// See com.sun.tools.javac.api.ClientCodeWrapper.DiagnosticSourceUnwrapper
val diagnostic = d.getClass.getField("d").get(d)
// See com.sun.tools.javac.util.JCDiagnostic#getDiagnosticSource
val getDiagnosticSourceMethod = diagnostic.getClass.getDeclaredMethod("getDiagnosticSource")
Option(getDiagnosticSourceMethod.invoke(diagnostic)) match {
case Some(diagnosticSource) =>
// See com.sun.tools.javac.util.DiagnosticSource
val getLineMethod = diagnosticSource.getClass.getMethod("getLine", Integer.TYPE)
Option(getLineMethod.invoke(diagnosticSource, line.get())).map(_.toString)
case _ => None
}
case _ => ""
}
} catch {
case ignored: NoSuchMethodException => None
case ignored: NoSuchFieldException => None
}
def getExpression: String =
Option(d.getSource) match {
case Some(source: JavaFileObject) =>
(Option(source.getCharContent(true)), startPosition, endPosition) match {
case (Some(cc), Some(start), Some(end)) => cc.subSequence(start.toInt, end.toInt).toString
case _ => ""
}
case _ => ""
}
getDiagnosticLine.getOrElse(getExpression)
}
private val sourceUri = fixSource(d.getSource)
override val sourcePath = Logger.o2m(sourceUri)
override val sourceFile = Logger.o2m(sourceUri.map(new File(_)))

View File

@ -60,7 +60,8 @@ object JavaCompilerSpec extends Specification {
val (result, problems) = compile(compiler, Seq(knownSampleErrorFile), Seq("-deprecation"))
val errored = result must beFalse
val foundErrorAndWarning = problems must haveSize(5)
val hasKnownErrors = problems.toSeq must contain(errorOnLine(1), warnOnLine(7))
val importWarn = warnOnLine(lineno = 1, lineContent = Some("import java.rmi.RMISecurityException;"))
val hasKnownErrors = problems.toSeq must contain(importWarn, errorOnLine(3), warnOnLine(7))
errored and foundErrorAndWarning and hasKnownErrors
}
@ -107,20 +108,28 @@ object JavaCompilerSpec extends Specification {
leftCompiled and rightCompiled and apisExpectedMatch
}
def lineMatches(p: Problem, lineno: Int): Boolean =
p.position.line.isDefined && (p.position.line.get == lineno)
def lineMatches(p: Problem, lineno: Int, lineContent: Option[String] = None): Boolean = {
def lineContentCheck =
lineContent match {
case Some(content) => content.equalsIgnoreCase(p.position.lineContent())
case _ => true
}
def lineNumberCheck = p.position.line.isDefined && (p.position.line.get == lineno)
lineNumberCheck && lineContentCheck
}
def isError(p: Problem): Boolean = p.severity == Severity.Error
def isWarn(p: Problem): Boolean = p.severity == Severity.Warn
def errorOnLine(lineno: Int) =
def errorOnLine(lineno: Int, lineContent: Option[String] = None) =
beLike[Problem]({
case p if lineMatches(p, lineno) && isError(p) => ok
case _ => ko
case p if lineMatches(p, lineno, lineContent) && isError(p) => ok
case _ => ko
})
def warnOnLine(lineno: Int) =
def warnOnLine(lineno: Int, lineContent: Option[String] = None) =
beLike[Problem]({
case p if lineMatches(p, lineno) && isWarn(p) => ok
case _ => ko
case p if lineMatches(p, lineno, lineContent) && isWarn(p) => ok
case _ => ko
})
def forkSameAsLocal = {