Skip to content

Commit

Permalink
LSP - in progress
Browse files Browse the repository at this point in the history
  • Loading branch information
neowit committed Apr 15, 2018
1 parent 718258b commit 840bc9a
Show file tree
Hide file tree
Showing 5 changed files with 158 additions and 11 deletions.
4 changes: 2 additions & 2 deletions src/main/scala/com/neowit/apex/Runner.scala
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ class Executor extends Logging {
} catch {
case ex: InvalidCommandLineException =>
if (null != ex.getMessage) {
basicConfig.getResponseWriter.send(ex.getMessage)
basicConfig.getResponseWriter.sendError("Invalid parameter: ", ex)
logger.error(ex.getMessage)
}
basicConfig.help()
Expand All @@ -78,7 +78,7 @@ class Executor extends Logging {
System.out.println(stackTraceStr)
*/
if (ex.message.nonEmpty) {
basicConfig.getResponseWriter.send(ex.message)
basicConfig.getResponseWriter.sendError("", ex)
logger.error(ex.message)
}
help(ex.help)
Expand Down
35 changes: 28 additions & 7 deletions src/main/scala/com/neowit/apex/lsp/ApexLanguageServerBase.scala
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import com.neowit.apex.{Executor, ProjectsCache, Session}
import com.neowit.apexscanner.Project
import com.neowit.apexscanner.server.LanguageServerDefault
import com.neowit.apexscanner.server.protocol.messages._
import com.neowit.response.protocols.lsp.ResponseWriterLsp
import com.neowit.utils.{BasicConfig, FileUtils}

import scala.concurrent.{ExecutionContext, Future}
Expand Down Expand Up @@ -132,20 +133,40 @@ class ApexLanguageServerBase(inputStream: InputStream, outputStream: OutputStrea
}
}

override def executeCommand(messageId: Int, params: MessageParams.ExecuteCommandParams, projectOpt: Option[Project]): Future[Either[ResponseError, ResponseMessage]] = {
logger.debug("execute command: " + params.command + " with arguments: " + params.arguments + " in project: " + projectOpt.map(_.path).getOrElse(""))
override def executeCommand(messageId: Int, params: MessageParams.ExecuteCommandParams, projectOpt: Option[Project]): Future[ResponseMessage] = {
val logMsg = "execute command: " + params.command + " with arguments: " + params.arguments + " in project: " + projectOpt.map(_.path).getOrElse("")
logger.debug(logMsg)
sendLogMessageNotification(MessageType.Log, logMsg)

val commandLineArgsMap: Map[String, String] = messageParamsToMap(params, projectOpt)
val responseWriter = new ResponseWriterLsp(messageId, this)
val runner = new Executor()

runner.basicConfig.setResponseWriter(responseWriter)
runner.execute(commandLineArgsMap)
super.executeCommand(messageId, params, projectOpt)
responseWriter.result() match {
case Some(msg) =>
Future.successful(msg)
case None =>
Future.successful(ResponseMessage(messageId, result = None, error = None))
}
}
override def executeCommand(messageId: Int, command: String): Future[Either[ResponseError, ResponseMessage]] = {
logger.debug("execute command: " + command + " without arguments")
override def executeCommand(messageId: Int, command: String): Future[ResponseMessage] = {
val logMsg = "execute command: " + command + " without arguments"
logger.debug(logMsg)
sendLogMessageNotification(MessageType.Log, logMsg)

val commandLineArgs: Array[String] = Array("--action=" + command)
val responseWriter = new ResponseWriterLsp(messageId, this)

val runner = new Executor()
runner.basicConfig.setResponseWriter(responseWriter)
runner.execute(commandLineArgs)
Future.successful(Right(ResponseMessage(messageId, result = None, error = None)))
responseWriter.result() match {
case Some(msg) =>
Future.successful(msg)
case None =>
Future.successful(ResponseMessage(messageId, result = None, error = None))
}
}

private def messageParamsToMap(params: MessageParams.ExecuteCommandParams, projectOpt: Option[Project]): Map[String, String] = {
Expand Down
7 changes: 5 additions & 2 deletions src/main/scala/com/neowit/response/ResponseWriter.scala
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ package com.neowit.response
import java.io.File

import com.neowit.apex.actions.ActionResult
import com.neowit.utils.{FileUtils, JsonSupport, Logging}
import com.neowit.utils.{FileUtils, Logging}

object ResponseWriter {

Expand Down Expand Up @@ -74,10 +74,13 @@ object ResponseWriter {
}


trait ResponseWriter extends Logging with JsonSupport {
trait ResponseWriter extends Logging {

def sendResponse(result: ActionResult): Unit
def send(msg: Message): Message
def sendError(msg: String, ex: Exception): Unit = {
send(msg + " " + ex.getMessage)
}
def send(msg: String): Unit
def send(msg: RESULT): Unit

Expand Down
43 changes: 43 additions & 0 deletions src/main/scala/com/neowit/response/protocols/lsp/AppVersion.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/*
* Copyright (c) 2018 Andrey Gavrikov.
* this file is part of tooling-force.com application
* https://github.com/neowit/tooling-force.com
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

package com.neowit.response.protocols.lsp

import com.neowit.apex.actions.ActionSuccess
import com.neowit.response._

class AppVersion(writer: ResponseWriterLsp) extends LspProtocol[AppVersionResult] {
def send(result: AppVersionResult): Unit = {
val msg =
result.appName + " - version: " + result.appVersion +
"; SFDC API Version: " + result.sfdcApiVersion +
"; java: " + result.javaVersion +
"; OS: " + result.os

writer.sendResponse(ActionSuccess(msg))

val mb = 1024*1024
val runtime = Runtime.getRuntime

writer.debug( s"Used Memory: ${(runtime.totalMemory - runtime.freeMemory) / mb} MB")
writer.debug( s"Free Memory: ${runtime.freeMemory / mb} MB")
writer.debug( s"Total Memory: ${runtime.totalMemory / mb} MB")
writer.debug( s"Max Memory: ${runtime.maxMemory / mb} MB")
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
/*
* Copyright (c) 2018 Andrey Gavrikov.
* this file is part of tooling-force.com application
* https://github.com/neowit/tooling-force.com
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

package com.neowit.response.protocols.lsp

import java.io.{PrintWriter, StringWriter}

import com.neowit.apex.actions.{ActionFailure, ActionResult, ActionSuccess}
import com.neowit.apexscanner.server.protocol.LanguageServer
import com.neowit.apexscanner.server.protocol.messages._
import com.neowit.response
import com.neowit.response.{BaseResult, RESULT, ResponseWriter}
import com.neowit.utils.Logging

import io.circe.syntax._
/**
* Created by Andrey Gavrikov
*/
trait LspProtocol[A <: BaseResult] {
def send(result: A): Unit
}
class ResponseWriterLsp(messageId: Int, server: LanguageServer) extends ResponseWriter with Logging with MessageJsonSupport {
private var _responseMessage: Option[ResponseMessage] = None

override def sendResponse(result: ActionResult): Unit = {
// TODO - implement proper handling of messages and resultOpt

result match {
case ActionSuccess(messages, resultOpt) =>
val totalMessage = messages.mkString("; ")
_responseMessage = Option(ResponseMessage(messageId, result = Option(totalMessage.asJson), error = None))
case ActionFailure(messages, resultOpt) =>
val totalMessage = messages.mkString("; ")
val error = ResponseError(0, totalMessage, messageId = Option(messageId))
_responseMessage = Option(ResponseMessage(messageId, result = None, Option(error)))
}
}

override def send(msg: response.Message): response.Message = throw new UnsupportedOperationException

override def send(msg: String): Unit = throw new UnsupportedOperationException

override def send(msg: RESULT): Unit = throw new UnsupportedOperationException

override def sendError(msg: String, ex: Exception): Unit = {
val sw = new StringWriter
ex.printStackTrace(new PrintWriter(sw))
val stackTraceStr = sw.toString
// dump exception information to log
logger.error(ex.getMessage)
logger.error(stackTraceStr)

val err = ResponseError(0, msg + ex.getMessage + "\n" + stackTraceStr)
_responseMessage = Option(ResponseMessage(messageId, result = None, error = Option(err)))
}

override def close(): Unit = ()

def debug(msg: String): Unit = {
server.sendLogMessageNotification(MessageType.Log, msg)
}

def result(): Option[ResponseMessage] = _responseMessage
}

0 comments on commit 840bc9a

Please sign in to comment.