Misc Visualization Fixes (#1328)

add: missing to_json conversions
fix: NPE in instrumentation
fix: EditFileCmd scheduling
fix: send visualization errors to the text endpoint
fix: preserve original location in the VectorLiterals pass
This commit is contained in:
Dmitry Bushev 2020-12-09 13:44:03 +03:00 committed by GitHub
parent f759dde7c8
commit 95a345ee26
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
23 changed files with 115 additions and 9 deletions

View File

@ -60,6 +60,10 @@ type Date
to_text : Text to_text : Text
to_text = Time_Utils.default_date_formatter [] . format [this.internal_local_date] to_text = Time_Utils.default_date_formatter [] . format [this.internal_local_date]
## A Date to Json conversion.
to_json : Json.Object
to_json = Json.from_pairs [["type", "Date"], ["day", this.day], ["month", this.month], ["year", this.year]]
## Format this date using formatter text. ## Format this date using formatter text.
Patterns are based on a simple sequence of letters and symbols. For Patterns are based on a simple sequence of letters and symbols. For

View File

@ -78,6 +78,20 @@ type Duration
to_vector : Vector.Vector to_vector : Vector.Vector
to_vector = [this.years, this.months, this.days, this.hours, this.minutes, this.seconds, this.nanoseconds] to_vector = [this.years, this.months, this.days, this.hours, this.minutes, this.seconds, this.nanoseconds]
## A Duration to Json conversion.
to_json : Json.Object
to_json =
b = Vector.new_builder
b.append ["type", "Duration"]
if not this.years==0 then b.append ["years", this.years]
if not this.months==0 then b.append ["months", this.months]
if not this.days==0 then b.append ["days", this.days]
if not this.hours==0 then b.append ["hours", this.hours]
if not this.minutes==0 then b.append ["minutes", this.minutes]
if not this.seconds==0 then b.append ["seconds", this.seconds]
if not this.nanoseconds==0 then b.append ["nanoseconds", this.nanoseconds]
Json.from_pairs b.to_vector
## Check if this duration is date-based. ## Check if this duration is date-based.
is_date : Boolean is_date : Boolean
is_date = (not this.years==0) || (not this.months==0) || (not this.days==0) is_date = (not this.years==0) || (not this.months==0) || (not this.days==0)

View File

@ -188,10 +188,19 @@ type Locale
to_text : Text | Nothing to_text : Text | Nothing
to_text = this.java_locale.toLanguageTag [] to_text = this.java_locale.toLanguageTag []
## A Locale to Json conversion
to_json : Json.Object
to_json =
b = Vector.new_builder
b.append ["type", "Locale"]
if not this.language.is_nothing then b.append ["language", this.language]
if not this.country.is_nothing then b.append ["country", this.country]
if not this.variant.is_nothing then b.append ["variant", this.variant]
Json.from_pairs b.to_vector
## PRIVATE ## PRIVATE
from_java : JavaLocale -> Locale from_java : JavaLocale -> Locale
from_java java = Locale java from_java java = Locale java
## PRIVATE ## PRIVATE
javaLocaleBuilder = Polyglot.get_member JavaLocale "Builder" javaLocaleBuilder = Polyglot.get_member JavaLocale "Builder"

View File

@ -112,6 +112,10 @@ type Time
to_text : Text to_text : Text
to_text = Time_Utils.default_time_formatter [] . format [this.internal_zoned_date_time] to_text = Time_Utils.default_time_formatter [] . format [this.internal_zoned_date_time]
## A Time to Json conversion.
to_json : Json.Object
to_json = Json.from_pairs [["type", "Time"], ["year", this.year], ["month", this.month], ["day", this.day], ["hour", this.hour], ["minute", this.minute], ["second", this.second], ["nanosecond", this.nanosecond], ["zone", this.zone]]
## Format this time using formatter text. ## Format this time using formatter text.
Patterns are based on a simple sequence of letters and symbols. For Patterns are based on a simple sequence of letters and symbols. For

View File

@ -65,6 +65,10 @@ type Time_Of_Day
to_text : Text to_text : Text
to_text = Time_Utils.default_time_of_day_formatter [] . format [this.internal_local_time] to_text = Time_Utils.default_time_of_day_formatter [] . format [this.internal_local_time]
## A Time_Of_Day to Json conversion.
to_json : Json.Object
to_json = Json.from_pairs [["type", "Time_Of_Day"], ["hour", this.hour], ["minute", this.minute], ["second", this.second], ["nanosecond", this.nanosecond]]
## Format this time of day using formatter text. ## Format this time of day using formatter text.
Patterns are based on a simple sequence of letters and symbols. For Patterns are based on a simple sequence of letters and symbols. For

View File

@ -15,6 +15,10 @@ type Zone
zone_id : Text zone_id : Text
zone_id = this.internal_zone_id . getId [] zone_id = this.internal_zone_id . getId []
## A Zone to Json conversion
to_json : Json.Object
to_json = Json.from_pairs [["type", "Zone"], ["id", this.zone_id]]
## This method parses the ID producing a `Zone`. ## This method parses the ID producing a `Zone`.
> Example > Example

View File

@ -24,3 +24,7 @@ type Response
## Get the response status code. ## Get the response status code.
code : Status_Code code : Status_Code
code = Status_Code.status_code (this.internal_http_response.statusCode []) code = Status_Code.status_code (this.internal_http_response.statusCode [])
## A Response to Json conversion.
to_json : Json.Object
to_json = Json.from_pairs [["type", "Response"], ["headers", this.headers], ["body", this.body], ["code", this.code]]

View File

@ -131,6 +131,10 @@ type Uri
to_text : Text to_text : Text
to_text = this.internal_uri.toString [] to_text = this.internal_uri.toString []
## An Uri to JSON conversion.
to_json : Json.String
to_json : Json.String this.to_text
## Check Uri equality. ## Check Uri equality.
== : Uri -> Boolean == : Uri -> Boolean
== that = this.internal_uri.equals [that.internal_uri] == that = this.internal_uri.equals [that.internal_uri]

View File

@ -219,6 +219,10 @@ type File
to_text : Text to_text : Text
to_text = this.prim_file.to_text to_text = this.prim_file.to_text
## A File to JSON conversion.
to_json : Json.Object
to_json = Json.from_pairs [["type", "File"], ["path", this.path]]
## Checks whether the file exists. ## Checks whether the file exists.
exists : Boolean exists : Boolean
exists = this.prim_file.exists [] exists = this.prim_file.exists []

View File

@ -102,7 +102,7 @@ final class ContextEventsListener(
val payload = val payload =
ContextRegistryProtocol.VisualisationEvaluationFailed(contextId, msg) ContextRegistryProtocol.VisualisationEvaluationFailed(contextId, msg)
sessionRouter ! DeliverToBinaryController(rpcSession.clientId, payload) sessionRouter ! DeliverToJsonController(rpcSession.clientId, payload)
case RunExpressionUpdates if expressionUpdates.nonEmpty => case RunExpressionUpdates if expressionUpdates.nonEmpty =>
def toMethodPointer(call: Api.MethodPointer): (String, String, String) = def toMethodPointer(call: Api.MethodPointer): (String, String, String) =

View File

@ -254,7 +254,7 @@ class ContextEventsListenerSpec
listener ! Api.VisualisationEvaluationFailed(contextId, message) listener ! Api.VisualisationEvaluationFailed(contextId, message)
router.expectMsg( router.expectMsg(
DeliverToBinaryController( DeliverToJsonController(
clientId, clientId,
VisualisationEvaluationFailed(contextId, message) VisualisationEvaluationFailed(contextId, message)
) )

View File

@ -197,7 +197,7 @@ public class IdExecutionInstrument extends TruffleInstrument {
FunctionCallInfo that = (FunctionCallInfo) o; FunctionCallInfo that = (FunctionCallInfo) o;
return Objects.equals(moduleName, that.moduleName) return Objects.equals(moduleName, that.moduleName)
&& Objects.equals(typeName, that.typeName) && Objects.equals(typeName, that.typeName)
&& functionName.equals(that.functionName); && Objects.equals(functionName, that.functionName);
} }
@Override @Override

View File

@ -99,9 +99,12 @@ case object VectorLiterals extends IRPass {
val trans = seq.mapExpressions(doExpression(_, vec)) val trans = seq.mapExpressions(doExpression(_, vec))
IR.Application.Prefix( IR.Application.Prefix(
vec.duplicate(), vec.duplicate(),
List(IR.CallArgument.Specified(None, trans, None, None)), List(
IR.CallArgument
.Specified(None, trans.copy(location = None), None, None)
),
false, false,
None trans.location
) )
} }
} }

View File

@ -23,6 +23,7 @@ class EditFileCmd(request: Api.EditFileNotification) extends Command(None) {
ec: ExecutionContext ec: ExecutionContext
): Future[Unit] = { ): Future[Unit] = {
ctx.locking.acquireFileLock(request.path) ctx.locking.acquireFileLock(request.path)
ctx.locking.acquirePendingEditsLock()
try { try {
ctx.executionService.getLogger ctx.executionService.getLogger
.log(Level.FINE, s"EditFileCmd ${request.path}") .log(Level.FINE, s"EditFileCmd ${request.path}")
@ -35,6 +36,7 @@ class EditFileCmd(request: Api.EditFileNotification) extends Command(None) {
_ <- Future.traverse(executeJobs)(ctx.jobProcessor.run) _ <- Future.traverse(executeJobs)(ctx.jobProcessor.run)
} yield () } yield ()
} finally { } finally {
ctx.locking.releasePendingEditsLock()
ctx.locking.releaseFileLock(request.path) ctx.locking.releaseFileLock(request.path)
} }
} }

View File

@ -35,6 +35,14 @@ trait Locking {
*/ */
def releaseReadCompilationLock(): Unit def releaseReadCompilationLock(): Unit
/** Acquires a pending edits lock.
*/
def acquirePendingEditsLock(): Unit
/** Releases a pending edits lock.
*/
def releasePendingEditsLock(): Unit
/** Acquires a context lock. /** Acquires a context lock.
* *
* @param contextId a context to lock * @param contextId a context to lock

View File

@ -11,6 +11,8 @@ class ReentrantLocking extends Locking {
private val compilationLock = new ReentrantReadWriteLock(true) private val compilationLock = new ReentrantReadWriteLock(true)
private val pendingEditsLock = new ReentrantLock()
private val contextMapLock = new ReentrantLock() private val contextMapLock = new ReentrantLock()
private var contextLocks = Map.empty[UUID, ReentrantLock] private var contextLocks = Map.empty[UUID, ReentrantLock]
@ -85,6 +87,14 @@ class ReentrantLocking extends Locking {
override def releaseReadCompilationLock(): Unit = override def releaseReadCompilationLock(): Unit =
compilationLock.readLock().unlock() compilationLock.readLock().unlock()
/** @inheritdoc */
override def acquirePendingEditsLock(): Unit =
pendingEditsLock.lock()
/** @inheritdoc */
override def releasePendingEditsLock(): Unit =
pendingEditsLock.unlock()
/** @inheritdoc */ /** @inheritdoc */
override def acquireContextLock(contextId: UUID): Unit = override def acquireContextLock(contextId: UUID): Unit =
getContextLock(contextId).lockInterruptibly() getContextLock(contextId).lockInterruptibly()

View File

@ -415,9 +415,12 @@ trait ProgramExecutionSupport {
} }
.leftMap(_.getMessage) .leftMap(_.getMessage)
.flatMap { .flatMap {
case text: String => Right(text.getBytes("UTF-8")) case text: String =>
case text: Text => Right(text.toString.getBytes("UTF-8")) Right(text.getBytes("UTF-8"))
case bytes: Array[Byte] => Right(bytes) case text: Text =>
Right(text.toString.getBytes("UTF-8"))
case bytes: Array[Byte] =>
Right(bytes)
case other => case other =>
Left(s"Cannot encode ${other.getClass} to byte array") Left(s"Cannot encode ${other.getClass} to byte array")
} }

View File

@ -65,6 +65,10 @@ spec =
time . second . should_equal 45 time . second . should_equal 45
time . nanosecond . should_equal 0 time . nanosecond . should_equal 0
time . zone . zone_id . should_equal Zone.utc.zone_id time . zone . zone_id . should_equal Zone.utc.zone_id
it "should convert to Json" <|
date = Date.new 2001 12 21
date.to_json.should_equal <|
Json.from_pairs [["type", "Date"], ["day", date.day], ["month", date.month], ["year", date.year]]
it "should add date-based interval" <| it "should add date-based interval" <|
date = Date.new 1970 + 1.day date = Date.new 1970 + 1.day
date . year . should_equal 1970 date . year . should_equal 1970

View File

@ -67,3 +67,8 @@ spec =
18.months.should_equal (1.year + 6.months) 18.months.should_equal (1.year + 6.months)
1.year.should_equal (11.months + 1.month) 1.year.should_equal (11.months + 1.month)
10.years.should_equal 10.years 10.years.should_equal 10.years
it "should convert to Json" <|
interval = 120.nanoseconds + 30.seconds + 14.hours + 12.days + 1.month + 9.years
interval.to_json.should_equal <|
duration_pairs = [["nanoseconds", interval.nanoseconds], ["seconds", interval.seconds], ["hours", interval.hours], ["days", interval.days], ["months", interval.months], ["years", interval.years]]
Json.from_pairs ([["type", "Duration"]] + duration_pairs)

View File

@ -55,3 +55,6 @@ spec = describe "Locale" <|
Locale.south_korea.to_text . should_equal "ko-KR" Locale.south_korea.to_text . should_equal "ko-KR"
Locale.uk.to_text . should_equal "en-GB" Locale.uk.to_text . should_equal "en-GB"
Locale.us.to_text . should_equal "en-US" Locale.us.to_text . should_equal "en-US"
it "should convert to Json" <|
en_gb.to_json.should_equal <|
Json.from_pairs [["type", "Locale"], ["language", "en"], ["country", "GB"]]

View File

@ -27,6 +27,11 @@ spec =
it "should format local time using default pattern" <| it "should format local time using default pattern" <|
text = Time_Of_Day.new 12 20 44 . to_text text = Time_Of_Day.new 12 20 44 . to_text
text . should_equal "12:20:44" text . should_equal "12:20:44"
it "should convert to Json" <|
time = Time_Of_Day.new 1 2 3
time.to_json.should_equal <|
time_pairs = [["hour", time.hour], ["minute", time.minute], ["second", time.second], ["nanosecond", time.nanosecond]]
Json.from_pairs ([["type", "Time_Of_Day"]] + time_pairs)
it "should parse default time format" <| it "should parse default time format" <|
text = Time_Of_Day.new 12 20 44 . to_text text = Time_Of_Day.new 12 20 44 . to_text
time = Time_Of_Day.parse text time = Time_Of_Day.parse text

View File

@ -29,6 +29,12 @@ spec =
it "should format using default pattern" <| it "should format using default pattern" <|
text = Time.new 1970 (zone = Zone.utc) . to_text text = Time.new 1970 (zone = Zone.utc) . to_text
text . should_equal "1970-01-01T00:00:00Z[UTC]" text . should_equal "1970-01-01T00:00:00Z[UTC]"
it "should convert to Json" <|
time = Time.new 1970 12 21 (zone = Zone.utc)
time.to_json.should_equal <|
zone_pairs = [["zone", Zone.utc]]
time_pairs = [["year", time.year], ["month", time.month], ["day", time.day], ["hour", time.hour], ["minute", time.minute], ["second", time.second], ["nanosecond", time.nanosecond]]
Json.from_pairs ([["type", "Time"]] + time_pairs + zone_pairs)
it "should parse default time format" <| it "should parse default time format" <|
text = Time.new 1970 (zone = Zone.utc) . to_text text = Time.new 1970 (zone = Zone.utc) . to_text
time = Time.parse text time = Time.parse text

View File

@ -22,3 +22,9 @@ spec =
it "should get utc zone id" <| it "should get utc zone id" <|
id = Zone.utc id = Zone.utc
id . zone_id . should_equal "UTC" id . zone_id . should_equal "UTC"
it "should convert to Json" <|
zone = Zone.new 1 2 3
zone.to_json.should_equal <|
Json.from_pairs [["type", "Zone"], ["id", "+01:02:03"]]
Zone.utc.to_json.should_equal <|
Json.from_pairs [["type", "Zone"], ["id", "UTC"]]