Skip to content
This repository has been archived by the owner on Mar 19, 2019. It is now read-only.

Commit

Permalink
Merge branch 'return-type'
Browse files Browse the repository at this point in the history
  • Loading branch information
jessitron committed Jan 19, 2017
2 parents 970b5d9 + f36392b commit 1c30454
Show file tree
Hide file tree
Showing 25 changed files with 166 additions and 171 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](http://semver.org/).

## [Unreleased]

### Changed

- TypeScript editors now return void. Use the new `ProjectMutableView` `describeChange` method to
add any comments about the working of your editor.


[Unreleased]: https://github.com/atomist/rug/compare/0.10.0...HEAD

### Fixed
Expand Down
6 changes: 0 additions & 6 deletions src/main/scala/com/atomist/project/edit/ProjectEditor.scala
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,6 @@ import com.atomist.source.ArtifactSource
*/
trait ProjectEditor extends ProjectDelta {

/**
* The expected impact of this editor. It may vary between applications,
* hence an Impact object will be returned in a SuccessfulModification
*/
def impacts: Set[Impact]

/**
* Attempt to create a new ArtifactSource based on applying this editor to the given one.
*
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.atomist.project.edit

import com.atomist.rug.kind.core.ChangeLogEntry
import com.atomist.source.ArtifactSource

/**
Expand All @@ -13,17 +14,15 @@ sealed trait ModificationAttempt
* @param result resulting ArtifactSource containing the changes.
* There must have been changed files. Otherwise,
* NoModificationNeeded or FailedModificationAttempt should have been returned.
* @param impacts the detailed impacts of the changes
* @param comment comments on what was done
*/
// TODO list files changed? - This could be more efficient in many cases
// Although this makes compounding harder. We could include Deltas as well.
// We could also add methods to make delta history must more efficient in ArtifactSource e.g. on + etc.
case class SuccessfulModification(
result: ArtifactSource,
impacts: Set[Impact],
comment: String
) extends ModificationAttempt
changeLogEntries: Seq[ChangeLogEntry[ArtifactSource]] = Nil
)
extends ModificationAttempt

/**
* Returned when no modification is needed, because the post condition
Expand All @@ -49,33 +48,10 @@ case class FailedModificationAttempt(failureExplanation: String,
*/
case class Applicability(canApply: Boolean, message: String) {

/**
* Are both these Applicability objects applicable?
*/
def and(that: Applicability) = Applicability(canApply && that.canApply, message + "/" + that.message)

def &&(that: Applicability) = this and that
}

object Applicability {

val OK = Applicability(canApply = true, "OK")
}

/**
* Tag supertrait for objects representing an impact of a code change.
*/
sealed trait Impact

object ContractImpact extends Impact
object CodeImpact extends Impact
object ConfigImpact extends Impact
object TestsImpact extends Impact
object CommentsImpact extends Impact
object ReadmeImpact extends Impact
object DependenciesImpact extends Impact

object Impacts {

val UnknownImpacts = Set(ContractImpact, CodeImpact, ConfigImpact, TestsImpact, CommentsImpact, ReadmeImpact, DependenciesImpact)
}
3 changes: 1 addition & 2 deletions src/main/scala/com/atomist/rug/RugProgram.scala
Original file line number Diff line number Diff line change
Expand Up @@ -86,8 +86,7 @@ case class RugEditor(
postcondition: Option[Condition],
parameters: Seq[Parameter],
computations: Seq[Computation],
actions: Seq[Action],
successBlock: Option[SuccessBlock]
actions: Seq[Action]
)
extends CanInvokeProjectOperation

Expand Down
18 changes: 18 additions & 0 deletions src/main/scala/com/atomist/rug/kind/core/ChangeCounting.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package com.atomist.rug.kind.core

/**
* Extended by classes with
* versioned backing objects
*/
trait ChangeCounting {

/**
*
* @return the number of revisions of this object. 0 means it has not
* been changed
*/
def changeCount: Int

def dirty: Boolean = changeCount > 0

}
32 changes: 32 additions & 0 deletions src/main/scala/com/atomist/rug/kind/core/ChangeLogging.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package com.atomist.rug.kind.core

import com.atomist.rug.spi.ExportFunction

case class ChangeLogEntry[S](
comment: String,
resultState: S
)

/**
* Extended by classes modeling mutable objects that undergo deliberate change
*/
trait ChangeLogging[S] {

private var _changeLogEntries: Seq[ChangeLogEntry[S]] = Seq()

protected def currentBackingObject: S

/**
* Describe a change we've made to this resource.
* Does not necessarily map 1:1 to versions as in changeCount
* @param comment message describing what we've done
*/
@ExportFunction(readOnly = false, description = "Describe a change we made to this object")
def describeChange(comment: String): Unit = {
val le = new ChangeLogEntry[S](comment, currentBackingObject)
_changeLogEntries = _changeLogEntries :+ le
}

def changeLogEntries: Seq[ChangeLogEntry[S]] = _changeLogEntries

}
26 changes: 15 additions & 11 deletions src/main/scala/com/atomist/rug/kind/core/ProjectMutableView.scala
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,12 @@ class ProjectMutableView(
atomistConfig: AtomistConfig,
projectOperations: Seq[ProjectOperation] = Nil,
ctx: UserModelContext = LocalAtomistFacade)
extends ArtifactContainerMutableView[ArtifactSource](originalBackingObject, null) {
extends ArtifactContainerMutableView[ArtifactSource](originalBackingObject, null)
with ChangeLogging[ArtifactSource] {

// We need this, rather than merely a default, for Java subclasses
def this(rugAs: ArtifactSource, originalBackingObject: ArtifactSource) =
this(rugAs, originalBackingObject, DefaultAtomistConfig)
this(rugAs, originalBackingObject, DefaultAtomistConfig)

import ProjectMutableView._

Expand All @@ -57,10 +58,10 @@ class ProjectMutableView(
private lazy val mergeTool =
new CombinedMergeToolCreator(MergeToolCreators: _*).createMergeTool(templateContent)

val TypeName: String = Typed.typeToTypeName(classOf[ProjectMutableView])
private val typeName: String = Typed.typeToTypeName(classOf[ProjectMutableView])

override def childrenNamed(fieldName: String): Seq[MutableView[_]] = fieldName match {
case TypeName =>
case `typeName` =>
// Special case. We don't want a "project" directory to confuse us
Seq(this)
case _ => kids(fieldName, this)
Expand Down Expand Up @@ -163,8 +164,8 @@ class ProjectMutableView(
/**
* Perform a regexp replace with the given file filter.
*
* @param filter file filter
* @param regexp regexp
* @param filter file filter
* @param regexp regexp
* @param replacement replacement for the regexp
*/
def regexpReplaceWithFilter(
Expand Down Expand Up @@ -348,7 +349,8 @@ class ProjectMutableView(
}

@ExportFunction(readOnly = false,
description = """Merge templates from the specified directory in the backing archive,
description =
"""Merge templates from the specified directory in the backing archive,
under /.atomist/templates, to the given output path in the project being
edited.""")
def mergeTemplates(@ExportFunctionParameterDescription(name = "templatesPath",
Expand Down Expand Up @@ -430,10 +432,11 @@ edited.""")
editWith(editorName, m)
}

@ExportFunction(readOnly = true, description="Return a new Project View based on the original backing object (normally the .atomist/ directory)")
def backingArchiveProject(): ProjectMutableView ={
new ProjectMutableView(EmptyArtifactSource.apply(),rugAs,atomistConfig,projectOperations)
@ExportFunction(readOnly = true, description = "Return a new Project View based on the original backing object (normally the .atomist/ directory)")
def backingArchiveProject(): ProjectMutableView = {
new ProjectMutableView(EmptyArtifactSource.apply(), rugAs, atomistConfig, projectOperations)
}

/**
* Convenient method to apply an editor.
*/
Expand All @@ -447,6 +450,7 @@ edited.""")
throw new RugRuntimeException(ed.name, s"Unexpected editor failure: $wtf", null)
}
}

@ExportFunction(readOnly = true,
description = "Provides access additional context, such as the PathExpressionEngine")
def context = new ProjectContext(ctx)
Expand All @@ -455,7 +459,7 @@ edited.""")

class ProjectContext(ctx: UserModelContext) extends UserServices {

override def pathExpressionEngine() : jsPathExpressionEngine = {
override def pathExpressionEngine(): jsPathExpressionEngine = {
ctx.registry("PathExpressionEngine").asInstanceOf[jsPathExpressionEngine]
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,6 @@ abstract class JavaParserProjectEditor(val name: String,
private val extractJavaFiles: ArtifactSource => Seq[FileArtifact] =
a => JavaFilesExtractor(a / javaSourcePath).asScala

override def impacts: Set[Impact] = Set(CodeImpact)

final override def applicability(as: ArtifactSource): Applicability = {
Applicability(JavaAssertions.isJava(as), "IsJava")
}
Expand Down Expand Up @@ -55,8 +53,7 @@ abstract class JavaParserProjectEditor(val name: String,
val result = as ✎ fe

result.allFiles.filter(_.name.endsWith("java")).foreach(f => logger.debug(s"${f.path}\n${f.content}\n"))

SuccessfulModification(result, impacts, s"$name success")
SuccessfulModification(result)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,12 @@ object ApplicationPropertiesToApplicationYmlEditor extends ProjectEditor with La

private val configExtractor = new ExtractApplicationProperties(source = ApplicationPropertiesFilePath)

override val impacts: Set[Impact] = Set(ConfigImpact)

override def modify(as: ArtifactSource, pmi: ProjectOperationArguments): ModificationAttempt = {
as.findFile(ApplicationPropertiesFilePath).map(f => {
val config = configExtractor(f)
val applicationYml: FileArtifact = StringFileArtifact(ApplicationYmlPath, toYmlString(config))
val result = as + applicationYml - ApplicationPropertiesFilePath
SuccessfulModification(result, impacts, name)
SuccessfulModification(result)
}).getOrElse(FailedModificationAttempt(s"Did not find application.properties file at $ApplicationPropertiesFilePath in ${as.id}"))
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import com.atomist.project.ProjectOperationArguments
import com.atomist.project.edit._
import com.atomist.project.edit.ProjectEditorSupport
import com.atomist.project.edit.ProjectEditorUtils._
import com.atomist.rug.kind.core.ChangeLogEntry
import com.atomist.source.ArtifactSource
import com.atomist.util.yml.{MapToYamlStringSerializer, PropertiesToMapStructureParser}

Expand Down Expand Up @@ -34,12 +35,9 @@ object ApplicationYmlKeyAddingEditor extends ProjectEditorSupport {
val result = appendToFile(as, yamlFile, stringifiedYamlEntries)
SuccessfulModification(
result,
impacts,
"Added keys to yaml file")
Seq(ChangeLogEntry("Added keys to yaml file", result)))
}

override def impacts: Set[Impact] = Set(ConfigImpact)

/**
* We can apply to anything. If a YML file doesn't exist, we'll create one.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -126,8 +126,6 @@ class ParserCombinatorRugParser(

private def compoundDoStep: Parser[Seq[DoStep]] = BeginToken ~> rep1(simpleWithDoStep) <~ EndToken

private def successBlock: Parser[SuccessBlock] = SuccessToken ~> literalString ^^ (message => SuccessBlock(message))

private def precondition: Parser[Condition] = PreconditionToken ~> capitalizedIdentifier ^^ (name => Condition(name))

private def postcondition: Parser[Condition] = PostconditionToken ~> capitalizedIdentifier ^^ (name => Condition(name))
Expand Down Expand Up @@ -170,12 +168,12 @@ class ParserCombinatorRugParser(
operationSpec(EditorToken) ~
rep(precondition) ~ opt(postcondition) ~
rep(parameter) ~ rep(letStatement) ~
opActions ~ opt(successBlock) ^^ {
case opSpec ~ preconditions ~ postcondition ~ params ~ compBlock ~ actions ~ success =>
opActions ^^ {
case opSpec ~ preconditions ~ postcondition ~ params ~ compBlock ~ actions =>
RugEditor(opSpec.name, opSpec.publishedName, opSpec.tags, opSpec.description, opSpec.imports,
preconditions, postcondition,
paramDefsToParameters(opSpec.name, params),
compBlock, actions, success)
compBlock, actions)
}

private def rugReviewer: Parser[RugReviewer] =
Expand Down
4 changes: 1 addition & 3 deletions src/main/scala/com/atomist/rug/rugdoc/TypeDoc.scala
Original file line number Diff line number Diff line change
Expand Up @@ -100,11 +100,9 @@ class TypeDoc(
override def modify(as: ArtifactSource, poa: ProjectOperationArguments): ModificationAttempt = {
val createdFile = createFile(poa)
val r = as + createdFile
SuccessfulModification(r, impacts, "OK")
SuccessfulModification(r)
}

override def impacts: Set[Impact] = Set(ReadmeImpact)

override def applicability(as: ArtifactSource): Applicability = Applicability.OK

override def description: String = "Generate core Rug type info"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,17 +13,15 @@ import jdk.nashorn.api.scripting.ScriptObjectMirror
* ProjectEditor implementation that invokes a JavaScript function.
*/
class JavaScriptInvokingProjectEditor(
jsc: JavaScriptContext,
jsVar: ScriptObjectMirror,
rugAs: ArtifactSource
)
jsc: JavaScriptContext,
jsVar: ScriptObjectMirror,
rugAs: ArtifactSource
)
extends JavaScriptInvokingProjectOperation(jsc, jsVar, rugAs)
with ProjectEditorSupport {

override val name: String = jsVar.getMember("name").asInstanceOf[String]

override def impacts: Set[Impact] = Impacts.UnknownImpacts

override def applicability(as: ArtifactSource): Applicability = Applicability.OK

override protected def modifyInternal(
Expand All @@ -37,15 +35,15 @@ class JavaScriptInvokingProjectEditor(

try {
//important that we don't invoke edit on the prototype as otherwise all constructor effects are lost!
val res = invokeMemberWithParameters("edit",
invokeMemberWithParameters("edit",
wrapProject(pmv),
poa)

if (pmv.currentBackingObject == targetProject) {
NoModificationNeeded("OK")
}
else {
SuccessfulModification(pmv.currentBackingObject, impacts, "OK")
SuccessfulModification(pmv.currentBackingObject, pmv.changeLogEntries)
}
}
catch {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,6 @@ class RugDrivenProjectEditor(
pre.predicateOrReviewerName)
})

override def impacts: Set[Impact] = {
Set[Impact](CodeImpact)
}

override def applicability(artifactSource: ArtifactSource): Applicability = {
program.preconditions
.map(pre => Applicability(evaluateCondition(pre, artifactSource), ""))
Expand Down Expand Up @@ -84,10 +80,10 @@ class RugDrivenProjectEditor(

if (currentProjectState.currentBackingObject == as) {
NoModificationNeeded(
program.successBlock.map(m => m.message).getOrElse("OK"))
"OK")
} else
SuccessfulModification(currentProjectState.currentBackingObject, impacts,
program.successBlock.map(m => m.message).getOrElse("OK"))
SuccessfulModification(currentProjectState.currentBackingObject,
currentProjectState.changeLogEntries)
} catch {
case f: InstantEditorFailureException =>
FailedModificationAttempt(f.getMessage)
Expand Down
Loading

0 comments on commit 1c30454

Please sign in to comment.