Skip to content

Commit

Permalink
improvement: report QDox errors
Browse files Browse the repository at this point in the history
  • Loading branch information
kasiaMarek committed Dec 19, 2024
1 parent 1ce512a commit 33387ed
Show file tree
Hide file tree
Showing 6 changed files with 89 additions and 33 deletions.
2 changes: 1 addition & 1 deletion metals-bench/src/main/scala/bench/MetalsBench.scala
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ class MetalsBench {
def mtagsJavaParse(): Unit = {
javaDependencySources.foreach { input =>
JavaMtags
.index(input, includeMembers = true)
.index(input, includeMembers = true)(EmptyReportContext)
.index()
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -208,28 +208,6 @@ trait MtagsEnrichments extends ScalametaCommonEnrichments {
def toLocation(uri: URI): l.Location = new l.Location(uri.toString(), range)
}

implicit class XtensionPositionLspInverse(pos: l.Position) {

/**
* LSP position translated to scalameta position. Might return None if
* pos is not contained in input
*
* @param input file input the position relates to
* @return scalameta position with offset if the pos is contained in the file
*/
def toMeta(input: m.Input): Option[m.Position] = {
Try(
m.Position.Range(
input,
pos.getLine,
pos.getCharacter,
pos.getLine,
pos.getCharacter
)
).toOption
}
}

implicit class XtensionPositionMtags(pos: Position) {
def encloses(other: Position): Boolean =
pos.start <= other.start && pos.end >= other.end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ import scala.meta.pc.SymbolDocumentation
*
* Handles both javadoc and scaladoc.
*/
class Docstrings(index: GlobalSymbolIndex) {
class Docstrings(index: GlobalSymbolIndex)(implicit rc: ReportContext) {
val cache = new TrieMap[Content, SymbolDocumentation]()
private val logger = Logger.getLogger(classOf[Docstrings].getName)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@ class JavadocIndexer(
input: Input.VirtualFile,
fn: SymbolDocumentation => Unit,
contentType: ContentType
) extends JavaMtags(input, includeMembers = true) {
)(implicit rc: ReportContext)
extends JavaMtags(input, includeMembers = true) {
override def visitClass(
cls: JavaClass,
pos: Position,
Expand Down Expand Up @@ -171,15 +172,15 @@ object JavadocIndexer {
def all(
input: Input.VirtualFile,
contentType: ContentType
): List[SymbolDocumentation] = {
)(implicit rc: ReportContext): List[SymbolDocumentation] = {
val buf = List.newBuilder[SymbolDocumentation]
foreach(input, contentType)(buf += _)
buf.result()
}
def foreach(
input: Input.VirtualFile,
contentType: ContentType
)(fn: SymbolDocumentation => Unit): Unit = {
)(fn: SymbolDocumentation => Unit)(implicit rc: ReportContext): Unit = {
new JavadocIndexer(input, fn, contentType).indexRoot()
}
}
67 changes: 61 additions & 6 deletions mtags/src/main/scala/scala/meta/internal/mtags/JavaMtags.scala
Original file line number Diff line number Diff line change
@@ -1,11 +1,18 @@
package scala.meta.internal.mtags

import java.io.StringReader
import java.net.URI
import java.util.Comparator

import scala.util.control.NonFatal

import scala.meta.inputs.Input
import scala.meta.inputs.Position
import scala.meta.internal.jdk.CollectionConverters._
import scala.meta.internal.metals.CompilerRangeParamsUtils
import scala.meta.internal.metals.EmptyCancelToken
import scala.meta.internal.metals.Report
import scala.meta.internal.metals.ReportContext
import scala.meta.internal.mtags.ScalametaCommonEnrichments._
import scala.meta.internal.semanticdb.Language
import scala.meta.internal.semanticdb.SymbolInformation.Kind
Expand All @@ -19,16 +26,18 @@ import com.thoughtworks.qdox.model.JavaMember
import com.thoughtworks.qdox.model.JavaMethod
import com.thoughtworks.qdox.model.JavaModel
import com.thoughtworks.qdox.parser.ParseException
import org.eclipse.lsp4j

object JavaMtags {
def index(
input: Input.VirtualFile,
includeMembers: Boolean
): MtagsIndexer =
)(implicit rc: ReportContext): MtagsIndexer =
new JavaMtags(input, includeMembers)
}
class JavaMtags(virtualFile: Input.VirtualFile, includeMembers: Boolean)
extends MtagsIndexer { self =>
class JavaMtags(virtualFile: Input.VirtualFile, includeMembers: Boolean)(
implicit rc: ReportContext
) extends MtagsIndexer { self =>
val builder = new JavaProjectBuilder()
override def language: Language = Language.JAVA

Expand All @@ -47,9 +56,14 @@ class JavaMtags(virtualFile: Input.VirtualFile, includeMembers: Boolean)
}
source.getClasses.asScala.foreach(visitClass)
} catch {
case _: ParseException | _: NullPointerException =>
// Parse errors are ignored because the Java source files we process
// are not written by the user so there is nothing they can do about it.
case e: ParseException =>
reportError(
"parse error",
e,
Some(new lsp4j.Position(e.getLine() - 1, e.getColumn()))
)
case e: NullPointerException =>
reportError("null pointer exception", e, None)
}
}

Expand Down Expand Up @@ -207,4 +221,45 @@ class JavaMtags(virtualFile: Input.VirtualFile, includeMembers: Boolean)
def lineNumber: Int = m.getLineNumber - 1
}

private def reportError(
errorName: String,
e: Exception,
position: Option[lsp4j.Position]
) = {
try {
val content = position
.flatMap(_.toMeta(virtualFile))
.map(pos =>
CompilerRangeParamsUtils.fromPos(pos, EmptyCancelToken).printed()
)
.map(content => s"""|
|file content:
|```java
|$content
|```
|""".stripMargin)
.getOrElse("")

val shortFileName = {
val index = virtualFile.path.indexOf("jar!")
if (index > 0) virtualFile.path.substring(index + 4)
else virtualFile.path
}

rc.unsanitized.create(
new Report(
name = "qdox-error",
text = s"""|error in qdox parser$content
|""".stripMargin,
error = Some(e),
path = Some(new URI(virtualFile.path)),
shortSummary = s"QDox $errorName in $shortFileName",
id = Some(virtualFile.path)
)
)
} catch {
case NonFatal(_) =>
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,28 @@ trait ScalametaCommonEnrichments extends CommonMtagsEnrichments {
}
}

implicit class XtensionPositionLspInverse(pos: l.Position) {

/**
* LSP position translated to scalameta position. Might return None if
* pos is not contained in input
*
* @param input file input the position relates to
* @return scalameta position with offset if the pos is contained in the file
*/
def toMeta(input: m.Input): Option[m.Position] = {
Try(
m.Position.Range(
input,
pos.getLine,
pos.getCharacter,
pos.getLine,
pos.getCharacter
)
).toOption
}
}

protected def filenameToLanguage(filename: String): Language = {
if (filename.endsWith(".java")) Language.JAVA
else if (
Expand Down

0 comments on commit 33387ed

Please sign in to comment.