Skip to content

Commit

Permalink
bugfix: Remove usage of some internal scalameta methods
Browse files Browse the repository at this point in the history
These methods are not checked by mima, so it's best to remove any usage of it.

There is still some internal methods, which we might want to move out from internal package in scalameta in the future, but theys are much less problematic
  • Loading branch information
tgodzik committed Oct 4, 2022
1 parent 17ac7c0 commit e9b8153
Show file tree
Hide file tree
Showing 6 changed files with 85 additions and 11 deletions.
30 changes: 23 additions & 7 deletions cli/src/main/scala/mdoc/internal/cli/CliEnrichments.scala
@@ -1,20 +1,20 @@
package mdoc.internal.cli

import coursierapi.Dependency

import java.io.PrintStream
import java.nio.charset.StandardCharsets
import java.nio.file.Files
import java.nio.file.Paths
import java.nio.file.StandardCopyOption
import scala.meta.Input
import scala.meta.Position
import scala.meta.internal.io.FileIO
import scala.meta.internal.io.PathIO
import scala.meta.io.AbsolutePath
import scala.meta.io.RelativePath
import scala.meta.internal.io.PathIO
import scala.util.control.NonFatal
import coursierapi.Dependency
import scala.meta.internal.io.FileIO
import scala.meta.internal.inputs._
import java.io.PrintStream
import scala.util.Try
import scala.util.control.NonFatal

trait CliEnrichments {
implicit class XtensionInputMdoc(input: Input) {
Expand All @@ -26,6 +26,12 @@ trait CliEnrichments {
Try(AbsolutePath(Paths.get(v.path)).filename).getOrElse(v.path)
case _ => input.syntax
}
def syntax: String = input match {
case Input.None => "<none>"
case Input.File(path, _) => path.toString
case Input.VirtualFile(path, _) => path
case _ => "<input>"
}
def relativeFilename(sourceroot: AbsolutePath): RelativePath =
input match {
case s: Input.Slice =>
Expand Down Expand Up @@ -64,7 +70,17 @@ trait CliEnrichments {
}
}

implicit class XtensionPositionMdoc(pos: Position) {
implicit class XtensionPositionMdoc(pos: Position) extends InternalInput(pos.input) {
def lineContent: String = {
val input = pos.input
val start = lineToOffset(pos.startLine)
val notEof = start < input.chars.length
val end = if (notEof) lineToOffset(pos.startLine + 1) else start
new String(input.chars, start, end - start).stripLineEnd
}
def lineCaret: String = {
" " * pos.startColumn + "^"
}
def addStart(offset: Int): Position =
pos match {
case Position.Range(i, start, end) =>
Expand Down
62 changes: 62 additions & 0 deletions cli/src/main/scala/mdoc/internal/cli/InternalInput.scala
@@ -0,0 +1,62 @@
package mdoc.internal.cli

import scala.collection.mutable
import scala.meta.inputs._
import scala.meta.Dialect
import scala.meta.tokens.Tokens
import scala.meta.internal.tokenizers.Compat

// Copied over from scalameta/scalameta
abstract class InternalInput(input: Input) {

// NOTE: It's regrettable that we need to taint the pure abstraction of Input.
// However, as #334 shows, we just can't redo offset -> line conversions over and over again.
// This means that we gotta cache, and this instance is really the only place versatile enough.
private lazy val cachedLineIndices: Array[Int] = {
val chars = input.chars
val buf = new mutable.ArrayBuffer[Int]
buf += 0
var i = 0
while (i < chars.length) {
if (chars(i) == '\n') buf += (i + 1)
i += 1
}
if (buf.last != chars.length) buf += chars.length // sentinel value used for binary search
buf.toArray
}

def lineToOffset(line: Int): Int = {
// NOTE: The length-1 part is not a typo, it's to accommodate the sentinel value.
if (!(0 <= line && line <= cachedLineIndices.length - 1)) {
val message =
s"$line is not a valid line number, allowed [0..${cachedLineIndices.length - 1}]"
throw new IllegalArgumentException(message)
}
cachedLineIndices(line)
}

def offsetToLine(offset: Int): Int = {
val chars = input.chars
val a = cachedLineIndices
// NOTE: We allow chars.length, because it's a valid value for an offset.
if (!(0 <= offset && offset <= chars.length)) {
val message = s"$offset is not a valid offset, allowed [0..${chars.length}]"
throw new IllegalArgumentException(message)
}
// NOTE: chars.length requires a really ugly special case.
// If the file doesn't end with \n, then it's simply last_line:last_col+1.
// But if the file does end with \n, then it's last_line+1:0.
if (offset == chars.length && (0 < chars.length && chars(offset - 1) == '\n')) {
return a.length - 1
}
var lo = 0
var hi = a.length - 1
while (hi - lo > 1) {
val mid = (hi + lo) / 2
if (offset < a(mid)) hi = mid
else if (a(mid) == offset) return mid
else /* if (a(mid) < offset */ lo = mid
}
lo
}
}
Expand Up @@ -29,7 +29,6 @@ import scala.tools.nsc.io.VirtualDirectory
import scala.annotation.implicitNotFound
import mdoc.internal.CompatClassloader
import mdoc.internal.worksheets.Compat._
import scala.meta.internal.inputs._

class MarkdownCompiler(
classpath: String,
Expand Down
Expand Up @@ -27,7 +27,6 @@ import scala.meta.Classpath
import scala.meta.AbsolutePath
import scala.meta.inputs.Input
import scala.meta.inputs.Position
import scala.meta.internal.inputs.XtensionInputSyntaxStructure

import dotty.tools.dotc.interactive.InteractiveDriver
import dotty.tools.dotc.interactive.Interactive
Expand Down
1 change: 0 additions & 1 deletion mdoc/src/main/scala/mdoc/internal/markdown/Markdown.scala
@@ -1,6 +1,5 @@
package mdoc.internal.markdown

import scala.meta.internal.inputs._
import com.vladsch.flexmark.ext.yaml.front.matter.YamlFrontMatterBlock
import com.vladsch.flexmark.formatter.Formatter
import com.vladsch.flexmark.html.HtmlRenderer
Expand Down
1 change: 0 additions & 1 deletion mdoc/src/main/scala/mdoc/internal/pos/PositionSyntax.scala
Expand Up @@ -16,7 +16,6 @@ import scala.meta.internal.io.PathIO
import scala.util.control.NonFatal
import coursierapi.Dependency
import scala.meta.internal.io.FileIO
import scala.meta.internal.inputs._

object PositionSyntax extends CliEnrichments with CollectionEnrichments {
implicit class XtensionRangePositionMdoc(pos: RangePosition) {
Expand Down

0 comments on commit e9b8153

Please sign in to comment.