-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Tracer MVP * Module names and releasing * Remove version override
- Loading branch information
Showing
11 changed files
with
896 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -12,6 +12,7 @@ concurrency: | |
|
||
env: | ||
JAVA_OPTS: "-Xmx4G" | ||
RELEASE: yesh | ||
|
||
jobs: | ||
build: | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
{ | ||
"params": { | ||
"textDocument": { | ||
"uri": "file:///home/user/grammar.js", | ||
"languageId": "javascript", | ||
"version": 0, | ||
"text": "hello" | ||
} | ||
}, | ||
"jsonrpc": "2.0", | ||
"method": "textDocument/didOpen" | ||
} |
14 changes: 14 additions & 0 deletions
14
modules/lsp/src/test/resources/textDocument/documentSymbol.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
{ | ||
"id": 25, | ||
"method": "textDocument/documentSymbol", | ||
"params": { | ||
"textDocument": { | ||
"uri": "file:///home/user/README.md" | ||
}, | ||
"position": { | ||
"line": 14, | ||
"character": 0 | ||
} | ||
}, | ||
"jsonrpc": "2.0" | ||
} |
21 changes: 21 additions & 0 deletions
21
modules/tracer/backend/src/main/resources/assets/index.html
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
<!DOCTYPE html> | ||
<html lang="en"> | ||
|
||
<head> | ||
<title>Langoustine tracer</title> | ||
<meta charset="UTF-8"> | ||
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | ||
<!-- <link rel="stylesheet" href="/path/to/styles/default.min.css"> --> | ||
<!-- <script src="/path/to/highlight.min.js"></script> --> | ||
<!-- <script>hljs.highlightAll();</script> --> | ||
<style type = "text/css"> | ||
font-family: 'Wotfard',Futura,-apple-system,sans-serif; | ||
</style> | ||
</head> | ||
|
||
<body> | ||
<div id="appContainer"></div> | ||
<script src="/assets/main.js"></script> | ||
</body> | ||
|
||
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
package langoustine.tracer | ||
|
||
import fs2.Stream | ||
import cats.effect.* | ||
import cats.syntax.all.* | ||
import scala.jdk.CollectionConverters.* | ||
import java.io.OutputStream | ||
|
||
trait ChildProcess[F[_]]: | ||
def stdin: fs2.Pipe[F, Byte, Unit] | ||
def stdout: Stream[F, Byte] | ||
def stderr: Stream[F, Byte] | ||
|
||
object ChildProcess: | ||
|
||
def spawn[F[_]: Async](command: String*): Stream[F, ChildProcess[F]] = | ||
Stream.bracket(start[F](command))(_._2).map(_._1) | ||
|
||
val readBufferSize = 512 | ||
private def start[F[_]: Async](command: Seq[String]) = | ||
Async[F].interruptible { | ||
val p = | ||
new java.lang.ProcessBuilder(command.asJava) | ||
.start() // .directory(new java.io.File(wd)).start() | ||
val done = Async[F].fromCompletableFuture(Sync[F].delay(p.onExit())) | ||
|
||
val terminate: F[Unit] = Sync[F].interruptible(p.destroy()) | ||
|
||
import cats.* | ||
val onGlobal = new (F ~> F): | ||
def apply[A](fa: F[A]): F[A] = | ||
Async[F].evalOn(fa, scala.concurrent.ExecutionContext.global) | ||
|
||
val cp = new ChildProcess[F]: | ||
def stdin: fs2.Pipe[F, Byte, Unit] = | ||
writeOutputStreamFlushingChunks[F]( | ||
Sync[F].interruptible(p.getOutputStream()) | ||
) | ||
|
||
def stdout: fs2.Stream[F, Byte] = fs2.io | ||
.readInputStream[F]( | ||
Sync[F].interruptible(p.getInputStream()), | ||
chunkSize = readBufferSize | ||
) | ||
.translate(onGlobal) | ||
|
||
def stderr: fs2.Stream[F, Byte] = fs2.io | ||
.readInputStream[F]( | ||
Sync[F].blocking(p.getErrorStream()), | ||
chunkSize = readBufferSize | ||
) | ||
.translate(onGlobal) | ||
// Avoids broken pipe - we cut off when the program ends. | ||
// Users can decide what to do with the error logs using the exitCode value | ||
.interruptWhen(done.void.attempt) | ||
(cp, terminate) | ||
} | ||
|
||
/** Adds a flush after each chunk | ||
*/ | ||
def writeOutputStreamFlushingChunks[F[_]]( | ||
fos: F[OutputStream], | ||
closeAfterUse: Boolean = true | ||
)(implicit F: Sync[F]): fs2.Pipe[F, Byte, Nothing] = | ||
s => | ||
def useOs(os: OutputStream): Stream[F, Nothing] = | ||
s.chunks.foreach(c => | ||
F.interruptible(os.write(c.toArray)) >> F.blocking(os.flush()) | ||
) | ||
|
||
val os = | ||
if closeAfterUse then Stream.bracket(fos)(os => F.blocking(os.close())) | ||
else Stream.eval(fos) | ||
os.flatMap(os => useOs(os) ++ Stream.exec(F.blocking(os.flush()))) | ||
end ChildProcess |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
package langoustine.tracer | ||
|
||
import org.http4s.* | ||
import cats.effect.* | ||
import org.http4s.dsl.io.* | ||
import java.nio.file.Paths | ||
|
||
object Static: | ||
def routes = | ||
val indexHtml = StaticFile | ||
.fromResource[IO]( | ||
"assets/index.html", | ||
None, | ||
preferGzipped = true | ||
) | ||
.getOrElseF(NotFound()) | ||
|
||
HttpRoutes.of[IO] { | ||
case req @ GET -> Root / "assets" / filename | ||
if filename.endsWith(".js") || filename.endsWith(".js.map") => | ||
StaticFile | ||
.fromResource[IO]( | ||
Paths.get("assets", filename).toString, | ||
Some(req), | ||
preferGzipped = true | ||
) | ||
.getOrElseF(NotFound()) | ||
case req @ GET -> Root => indexHtml | ||
case req if req.method == GET => indexHtml | ||
} | ||
end routes | ||
end Static |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
package langoustine | ||
package tracer | ||
|
||
import jsonrpclib.fs2.* | ||
import cats.effect.IOApp | ||
import cats.effect.ExitCode | ||
import cats.effect.IO | ||
import fs2.Chunk | ||
|
||
import org.http4s.EntityEncoder | ||
import jsonrpclib.Payload | ||
import jsonrpclib.ErrorPayload | ||
import jsonrpclib.CallId | ||
|
||
object Tracer extends IOApp: | ||
def run(args: List[String]): IO[ExitCode] = | ||
val in = fs2.io.stdin[IO](512) | ||
val out = fs2.io.stdout[IO] | ||
|
||
val tracerArgs = args.takeWhile(_.startsWith("!")).map(_.drop(1)) | ||
|
||
val restArgs = args.drop(tracerArgs.length) | ||
|
||
val argMap = tracerArgs | ||
.grouped(2) | ||
.collect { case k :: v :: Nil => | ||
k -> v | ||
} | ||
.toMap | ||
|
||
val byteTopic = | ||
fs2.Stream.eval(fs2.concurrent.Channel.unbounded[IO, Chunk[Byte]]) | ||
|
||
byteTopic | ||
.flatMap { inBytes => | ||
byteTopic.flatMap { outBytes => | ||
byteTopic.flatMap { errBytes => | ||
ChildProcess | ||
.spawn[IO](restArgs*) | ||
.flatMap { child => | ||
|
||
val redirectInput = | ||
in.chunks.evalTap(inBytes.send).unchunks.through(child.stdin) | ||
|
||
val redirectOutput = | ||
child.stdout.chunks | ||
.evalTap(outBytes.send) | ||
.unchunks | ||
.through(out) | ||
|
||
redirectInput | ||
.concurrently(redirectOutput) | ||
.concurrently(child.stderr.chunks.evalTap(errBytes.send)) | ||
.concurrently( | ||
TracerServer | ||
.create( | ||
inBytes.stream.unchunks, | ||
outBytes.stream.unchunks, | ||
errBytes.stream.unchunks | ||
) | ||
.run(argMap) | ||
) | ||
} | ||
} | ||
} | ||
} | ||
.compile | ||
.drain | ||
.as(ExitCode(0)) | ||
end run | ||
end Tracer |
Oops, something went wrong.