Skip to content

Commit

Permalink
Merge branch 'release/2.0.12'
Browse files Browse the repository at this point in the history
  • Loading branch information
acunniffe committed Dec 4, 2018
2 parents de4fd8b + b94a177 commit 029dc9b
Show file tree
Hide file tree
Showing 55 changed files with 513 additions and 181 deletions.
2 changes: 1 addition & 1 deletion cli/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "optic-cli",
"version": "2.0.10",
"version": "2.0.12",
"description": "",
"main": "lib/Cli.js",
"scripts": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ object Evaluation {
val objName = rt.inputModelName
AnnotationRenderer.renderToFirstLine(
generatedNode._3.renderer.parser.inlineCommentPrefix,
Vector(SourceAnnotation(None, objName, transformation.transformationRef, rt.answers)),
Vector(SourceAnnotation(None, objName, transformation.transformationRef, rt.answers, false)),
generatedNode._2)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package com.opticdev.core.compiler.stages
import com.opticdev.core.compiler.errors.AstPathNotFound
import com.opticdev.core.compiler.helpers.FinderPath
import com.opticdev.core.compiler.{FinderStageOutput, ParserFactoryOutput, SnippetStageOutput}
import com.opticdev.core.sourcegear.accumulate.{AssignmentListener, MapSchemaListener}
import com.opticdev.core.sourcegear.accumulate.{AssignmentListener, ComputedFieldListener, Listener, MapSchemaListener}
import com.opticdev.core.sourcegear.containers.SubContainerManager
import com.opticdev.core.sourcegear.gears.RuleProvider
import com.opticdev.core.sourcegear.gears.parsing.{AdditionalParserInformation, NodeDescription, ParseAsModel}
Expand All @@ -15,7 +15,7 @@ import scalax.collection.edge.LkDiEdge
import scalax.collection.mutable.Graph
import com.opticdev.common.{PackageRef, SchemaRef}
import com.opticdev.core.sourcegear.project.config.options.DefaultSettings
import com.opticdev.sdk.skills_sdk.lens.OMLens
import com.opticdev.sdk.skills_sdk.lens._


class ParserFactoryStage(snippetStage: SnippetStageOutput, finderStageOutput: FinderStageOutput, schemaDefaultsOption: Option[DefaultSettings], internal: Boolean = false)(implicit lens: OMLens, variableManager: VariableManager = VariableManager.empty, subcontainersManager: SubContainerManager = SubContainerManager.empty) extends CompilerStage[ParserFactoryOutput] {
Expand All @@ -30,16 +30,23 @@ class ParserFactoryStage(snippetStage: SnippetStageOutput, finderStageOutput: Fi

val nodeDescription = ParserFactoryStage.nodeToDescription(enterOn)

val listeners = {
lens.valueSchemaComponentsCompilerInput.map(collectSchemaComponent =>
MapSchemaListener(collectSchemaComponent, lens.schemaRef, lens.packageRef.packageId)) ++
lens.assignmentComponentsCompilerInput.map(assignmentComponent => {
val pathOption = finderStageOutput.componentFinders.find(_._2.exists(_ == assignmentComponent)).map(i=> finderPathToFlatPath(i._1, enterOn))
AssignmentListener(assignmentComponent, pathOption, lens.schemaRef, lens.packageRef.packageId)
}
def listenersFromComponents(components: Vector[OMComponentWithPropertyPath[OMLensComponent]]): Vector[Listener] = components.map {
case as if as.containsAssignmentComponent => {
val pathOption = finderStageOutput.componentFinders.find(_._2.exists(_ == as)).map(i=> finderPathToFlatPath(i._1, enterOn))
AssignmentListener(as.asInstanceOf[OMComponentWithPropertyPath[OMLensAssignmentComponent]], pathOption, lens.schemaRef, lens.lensRef)
}
case sc if sc.containsSchemaComponent => MapSchemaListener(sc.asInstanceOf[OMComponentWithPropertyPath[OMLensSchemaComponent]], lens.schemaRef, lens.lensRef)
case cc if cc.containsComputedComponent => ComputedFieldListener(
cc.asInstanceOf[OMComponentWithPropertyPath[OMLensComputedFieldComponent]],
listenersFromComponents(cc.component.asInstanceOf[OMLensComputedFieldComponent].accumulatorInputComponents),
lens.lensRef
)
}

val listeners = listenersFromComponents(
(lens.valueSchemaComponentsCompilerInput ++ lens.assignmentComponentsCompilerInput ++ lens.computedFieldComponentsCompilerInput)
.asInstanceOf[Vector[OMComponentWithPropertyPath[OMLensComponent]]])

if (lens.schemaRef.packageRef.isDefined && lens.schemaRef.packageRef.get != lens.packageRef) {
//external schema
import com.opticdev.core.sourcegear.context.SDKObjectsResolvedImplicits._
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ class LensSet(initialGears: SGExportableLens*) {

multiNodeLensStore = lenses.collect{case mn: CompiledMultiNodeLens => mn}.toSet

fileAccumulator = FileAccumulator(allListeners.toSet.groupBy(_.mapToSchema))
fileAccumulator = FileAccumulator(allListeners.toSet.groupBy(_.lensRef))
}

def grouped: Map[AstType, Set[CompiledLens]] = groupedStore
Expand Down Expand Up @@ -111,7 +111,7 @@ class LensSet(initialGears: SGExportableLens*) {
val parsedAnnotations = AnnotationParser.annotationsFromFile(fileContents)(sourceGearContext.parser, sourceGearContext.file)
if (parsedAnnotations.nonEmpty) {
val modelAstPairs = modelNodes.map(i => (i, i.resolveInGraph[CommonAstNode](astGraph)))
val rangePair = modelAstPairs.map(i => (i._2.root.lineRange(fileContents), i._1.asInstanceOf[ModelNode]))
val rangePair = modelAstPairs.map(i => (i._2.root.lineRange(fileContents), i._1.asInstanceOf[ModelNode], i._2.root.range))
AnnotationSorting.sortAnnotations(rangePair, parsedAnnotations)
} else Map.empty
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ object Render {
val result = gear.renderer.renderWithNewAstNode(processedValue, containerContents, variableMapping)

val stringResult = if (options.tag.isDefined) {
AnnotationRenderer.renderToFirstLine(gear.renderer.parser.inlineCommentPrefix, Vector(TagAnnotation(options.tag.get, gear.schemaRef)), result._2)
AnnotationRenderer.renderToFirstLine(gear.renderer.parser.inlineCommentPrefix, Vector(TagAnnotation(options.tag.get, gear.schemaRef, false)), result._2)
} else {
result._2
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,36 +11,38 @@ import com.opticdev.common.graph.{AstGraph, CommonAstNode}
import com.opticdev.common.graph.path.{FlatWalkablePath, WalkablePath}
import com.opticdev.core.sourcegear.project.OpticProject
import com.opticdev.parsers.token_values.{External, Imported}
import com.opticdev.sdk.skills_sdk.LensRef
import com.opticdev.sdk.skills_sdk.lens.{OMComponentWithPropertyPath, OMLensAssignmentComponent}
import play.api.libs.json.JsString

import scala.util.Try

//@todo it's likely that multiple listeners will be created -- eventually combine them to reduce # of lookups.
case class AssignmentListener(assignmentComponent: OMComponentWithPropertyPath[OMLensAssignmentComponent], walkablePath: Option[FlatWalkablePath], mapToSchema: SchemaRef, packageId: String) extends Listener {
case class AssignmentListener(assignmentComponent: OMComponentWithPropertyPath[OMLensAssignmentComponent], walkablePath: Option[FlatWalkablePath], mapToSchema: SchemaRef, lensRef: LensRef) extends Listener {

override val schema: Option[SchemaRef] = None

override def collect(implicit astGraph: AstGraph, modelNode: BaseModelNode, sourceGearContext: SGContext): Option[ModelField] = {
val component = assignmentComponent.component
override def collect(implicit astGraph: AstGraph, modelNode: BaseModelNode, sourceGearContext: SGContext): Try[ModelField] = Try {
val assignmentOption: Option[ModelField] = {
val component = assignmentComponent.component

val asModelNode : ModelNode = modelNode match {
case l: LinkedModelNode[CommonAstNode] => l.flatten
case mN: ModelNode => mN
}
val asModelNode: ModelNode = modelNode match {
case l: LinkedModelNode[CommonAstNode] => l.flatten
case mN: ModelNode => mN
}

val astRoot = asModelNode.astRoot()
val astRoot = asModelNode.astRoot()

//from a token with a path
if (component.fromToken && walkablePath.isDefined) Try {
val variableNode = WalkablePath(astRoot, walkablePath.get.path, astGraph).walk()
//from a token with a path
if (component.fromToken && walkablePath.isDefined) {
val variableNode = WalkablePath(astRoot, walkablePath.get.path, astGraph).walk()

val entryOption = {
val nodeIdentifier = sourceGearContext.parser.identifierNodeDesc.parse(variableNode)
sourceGearContext.fileTokenRegistry.getExpanded(nodeIdentifier.get)
}
val entryOption = {
val nodeIdentifier = sourceGearContext.parser.identifierNodeDesc.parse(variableNode)
sourceGearContext.fileTokenRegistry.getExpanded(nodeIdentifier.get)
}

if (entryOption.isDefined) {
println(entryOption)

val (inScope, value) = entryOption.get match {
case imported: Imported[SGContext] => {
Expand All @@ -60,19 +62,16 @@ case class AssignmentListener(assignmentComponent: OMComponentWithPropertyPath[O
value.walk(component.keyPath)
}.get

return Some(ModelField(
Some(ModelField(
component.keyPath.split("\\."),
tokenValue,
operation = component.operation
))

} else return None
} else {
//not tied to a specific token (like collect)
None
}
} else None
} else None
}

None
assignmentOption.getOrElse(throw new Exception("Unable to resolve assignment"+ assignmentComponent.component))
}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package com.opticdev.core.sourcegear.accumulate

import com.opticdev.common.SchemaRef
import com.opticdev.common.graph.path.PropertyPathWalker
import com.opticdev.common.graph.{AstGraph, CommonAstNode}
import com.opticdev.core.sourcegear.SGContext
import com.opticdev.core.sourcegear.context.SDKObjectsResolvedImplicits._
import com.opticdev.core.sourcegear.gears.helpers.{LocationEvaluation, ModelField}
import com.opticdev.core.sourcegear.graph.GraphImplicits._
import com.opticdev.core.sourcegear.graph.model.{BaseModelNode, LinkedModelNode, ModelNode, ModelVectorMapping}
import com.opticdev.sdk.skills_sdk.lens.{OMComponentWithPropertyPath, OMLensCodeComponent, OMLensComputedFieldComponent, OMLensSchemaComponent}
import play.api.libs.json._
import com.opticdev.core.utils.GetKeyFromJsValue._
import com.opticdev.sdk.skills_sdk.LensRef

import scala.util.Try

case class ComputedFieldListener(computedField: OMComponentWithPropertyPath[OMLensComputedFieldComponent], sublisteners: Vector[Listener], lensRef: LensRef) extends Listener {

override def collect(implicit astGraph: AstGraph, modelNode: BaseModelNode, sourceGearContext: SGContext): Try[ModelField] = Try {
val hiddenValue = modelNode.hiddenValue

val numberOfComponents = computedField.component.subcomponents.size
val argumentsMap = scala.collection.mutable.HashMap[Int, Option[JsValue]](Range(0, numberOfComponents).map(i => (i, None)):_*)

//get arguments for all basic components
computedField.component.subcomponents.zipWithIndex.foreach{ case (component, i) =>
component match {
case code: OMLensCodeComponent => {
hiddenValue.walk(computedField.component.identifier, i.toString).foreach(value => argumentsMap.put(i, Some(value)))
}
case _ => None
}
}

//get arguments for all listeners
sublisteners.foreach({
case schemaListener: MapSchemaListener => {
val index = schemaListener.schemaComponent.propertyPath(1).toInt
val evaluated = schemaListener.collect(astGraph, modelNode, sourceGearContext)
argumentsMap.put(index,evaluated.map(_.value).toOption)
}
case assignmentListener: AssignmentListener => {
val index = assignmentListener.assignmentComponent.propertyPath(1).toInt
val evaluated = assignmentListener.collect(astGraph, modelNode, sourceGearContext)
argumentsMap.put(index, evaluated.map(_.value).toOption)
}
})


require(argumentsMap.forall(_._2.isDefined), "Computed Field can not be computed because required arguments could not be resolved")

val argsVector = {
val vec = argumentsMap.toVector.sortBy(_._1).map(_._2.get)
if (computedField.component.enforceUniqueArguments) vec.distinct else vec
}

computedField.component.fieldProcessor
.evaluate(argsVector)
.map(i=> ModelField(computedField.propertyPath, i)).get

}

override val schema: Option[SchemaRef] = None
override val mapToSchema: SchemaRef = null
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@ import com.opticdev.common.SchemaRef
import com.opticdev.core.sourcegear.gears.parsing.ParseResult
import com.opticdev.core.sourcegear.graph.GraphOperations
import com.opticdev.common.graph.{AstGraph, CommonAstNode}
import com.opticdev.sdk.skills_sdk.LensRef

case class FileAccumulator(listeners: Map[SchemaRef, Set[Listener]] = Map()) extends Accumulator {
case class FileAccumulator(listeners: Map[LensRef, Set[Listener]] = Map()) extends Accumulator {
override def run(implicit astGraph: AstGraph, parseResults: Vector[ParseResult[CommonAstNode]]): Unit = {
//after this graph will contain all Model Nodes from the file.
GraphOperations.addModelsToGraph(parseResults)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,17 @@ import com.opticdev.sdk.descriptions.enums.LocationEnums.InCurrentLens
import com.opticdev.core.sourcegear.context.SDKObjectsResolvedImplicits._
import com.opticdev.common.graph.path.PropertyPathWalker
import com.opticdev.core.sourcegear.project.OpticProject
import com.opticdev.sdk.skills_sdk.LensRef
import com.opticdev.sdk.skills_sdk.lens.{OMComponentWithPropertyPath, OMLensSchemaComponent}

import scala.util.Try

case class MapSchemaListener(schemaComponent: OMComponentWithPropertyPath[OMLensSchemaComponent], mapToSchema: SchemaRef, packageId: String) extends Listener {
case class MapSchemaListener(schemaComponent: OMComponentWithPropertyPath[OMLensSchemaComponent], mapToSchema: SchemaRef, lensRef: LensRef) extends Listener {

override val schema = Some(schemaComponent.component.schemaRef)
override def collect(implicit astGraph: AstGraph, modelNode: BaseModelNode, sourceGearContext: SGContext): Option[ModelField] = Try {
override def collect(implicit astGraph: AstGraph, modelNode: BaseModelNode, sourceGearContext: SGContext): Try[ModelField] = Try {

val resolvedSchema = schemaComponent.component.resolvedSchema(packageId)(sourceGearContext.sourceGear)
val resolvedSchema = schemaComponent.component.resolvedSchema(lensRef.packageRef.get.packageId)(sourceGearContext.sourceGear)

val asModelNode : ModelNode = modelNode match {
case l: LinkedModelNode[CommonAstNode] => l.flatten
Expand All @@ -39,7 +40,11 @@ case class MapSchemaListener(schemaComponent: OMComponentWithPropertyPath[OMLens

val found = {
val allFound = targetNodes
.filter(n => LocationEvaluation.matches(schemaComponent.component.locationForCompiler.get, n.astRoot, astRoot, containerMapping))
.filter(n => {
val correctLocation = LocationEvaluation.matches(schemaComponent.component.locationForCompiler.get, n.astRoot, astRoot, containerMapping)
val validSchema = n.matchesSchema()(sourceGearContext)
correctLocation && validSchema
})
.sortBy(_.astRoot.range.start)

PriorityFilter.apply(allFound:_*)
Expand Down Expand Up @@ -72,5 +77,5 @@ case class MapSchemaListener(schemaComponent: OMComponentWithPropertyPath[OMLens
} else {
ModelField(schemaComponent.propertyPath, JsArray(addToNodes.map(_.expandedValue())), ModelVectorMapping(addToNodes.map(i=> i.asInstanceOf[ModelNode])))
}
}.toOption
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,21 +6,25 @@ import com.opticdev.core.sourcegear.gears.parsing.ParseResult
import com.opticdev.core.sourcegear.graph.model.BaseModelNode
import com.opticdev.common.graph.{AstGraph, CommonAstNode}
import com.opticdev.core.sourcegear.project.OpticProject
import com.opticdev.sdk.skills_sdk.LensRef

import scala.util.Try

package object accumulate {

trait Accumulator {

val listeners : Map[SchemaRef, Set[Listener]]
val listeners : Map[LensRef, Set[Listener]]

def run(implicit astGraph: AstGraph, parseResults: Vector[ParseResult[CommonAstNode]]) : Unit

}

trait Listener {
def collect(implicit astGraph: AstGraph, modelNode: BaseModelNode, sourceGearContext: SGContext) : Option[ModelField]
def collect(implicit astGraph: AstGraph, modelNode: BaseModelNode, sourceGearContext: SGContext) : Try[ModelField]
val schema: Option[SchemaRef]
val mapToSchema: SchemaRef
def lensRef: LensRef
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ class ProjectActor(initialGraph: ProjectGraphWrapper)(implicit logToCli: Boolean
case i: ParseFailed => {
graph.removeFile(i.file, ignoreExceptions = true)
context.become(active(graph))
println("Failed to parse file "+ i.file)
println(Console.RED+ s"Failed to parse file: ${i.file} ${i.error}" +Console.RESET)
sender() ! graph
}
case deleted: FileDeleted => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,22 +22,23 @@ object AnnotationParser {
}

val allAnnotationLines = findAllAnnotationComments(parserBase.inlineCommentPrefix, parserBase.blockCommentRegex, contents)
allAnnotationLines.map{ case (lineNumber, line) =>
(lineNumber, AnnotationsDslParser.parseSingleLine(line)(ParseContext(file, lineNumber)))
allAnnotationLines.map{ case (lineNumber, line, isBlock) =>
(lineNumber, AnnotationsDslParser.parseSingleLine(line)(ParseContext(file, lineNumber)), isBlock)
}.collect {
case (line, n) if isType(n, "NameOperationNode") =>
(line, NameAnnotation(n.get.asInstanceOf[NameOperationNode].name, null))
case (line, n) if isType(n, "TagOperationNode") =>
(line, TagAnnotation(n.get.asInstanceOf[TagOperationNode].name, null))
case (line, n) if isType(n, "SetOperationNode") =>
(line, OverrideAnnotation(n.get.asInstanceOf[SetOperationNode].assignments))
case (line, n) if isType(n, "SourceOperationNode") => {
case (line, n, isBlock) if isType(n, "NameOperationNode") =>
(line, NameAnnotation(n.get.asInstanceOf[NameOperationNode].name, null, isBlock))
case (line, n, isBlock) if isType(n, "TagOperationNode") =>
(line, TagAnnotation(n.get.asInstanceOf[TagOperationNode].name, null, isBlock))
case (line, n, isBlock) if isType(n, "SetOperationNode") =>
(line, OverrideAnnotation(n.get.asInstanceOf[SetOperationNode].assignments, isBlock))
case (line, n, isBlock) if isType(n, "SourceOperationNode") => {
val sourceOperationNode = n.get.asInstanceOf[SourceOperationNode]
(line, SourceAnnotation(
sourceOperationNode.project,
sourceOperationNode.name,
sourceOperationNode.relationshipId.get, //@todo make implicit if not specified
sourceOperationNode.answers)
sourceOperationNode.answers,
isBlock)
)
}
}
Expand Down Expand Up @@ -81,9 +82,9 @@ object AnnotationParser {
})
}.toVector

def findAllAnnotationComments(inlineCommentPrefix: String, blockCommentRegex: Regex, contents: String) : Vector[(Int, String)] = {
(inlineAnnotationComments(inlineCommentPrefix, contents) ++
findBlockAnnotationComments(blockCommentRegex, contents)).sortBy(_._1)
def findAllAnnotationComments(inlineCommentPrefix: String, blockCommentRegex: Regex, contents: String) : Vector[(Int, String, Boolean)] = {
inlineAnnotationComments(inlineCommentPrefix, contents).map(i=> (i._1, i._2, false)) ++
findBlockAnnotationComments(blockCommentRegex, contents).map(i=> (i._1, i._2, true)).sortBy(_._1)
}

}
Loading

0 comments on commit 029dc9b

Please sign in to comment.