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

Commit

Permalink
Prepare for 1.0.0-m.2 release
Browse files Browse the repository at this point in the history
  • Loading branch information
kipz committed Apr 28, 2017
1 parent 5c86400 commit 7da3009
Show file tree
Hide file tree
Showing 3 changed files with 140 additions and 158 deletions.
9 changes: 8 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,21 @@ and this project adheres to [Semantic Versioning](http://semver.org/).

## [Unreleased]

[Unreleased]: https://github.com/atomist/rugs/compare/1.0.0-m.1...HEAD
[Unreleased]: https://github.com/atomist/rugs/compare/1.0.0-m.2...HEAD

## [1.0.0-m.2] - 2017-04-27

[1.0.0-m.2]: https://github.com/atomist/rugs/compare/1.0.0-m.1...1.0.0-m.2

Milestone 2 release

### Changed

- Use build script so successful builds get tagged

### Fixed

- Removed circular references between Enhance.ts and QueryByExample.ts
- Properly lint all TypeScript source files

## [1.0.0-m.1] - 2017-04-26
Expand Down
147 changes: 0 additions & 147 deletions util/tree/Enhance.ts

This file was deleted.

142 changes: 132 additions & 10 deletions util/tree/QueryByExample.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,7 @@

import { GraphNode, PathExpression } from "@atomist/rug/tree/PathExpression";

import { isArray, isFunction, isPrimitive } from "../misc/Utils";

import * as enhancer from "./Enhance";
import { match } from "./Enhance";
import { enhance } from "./Enhance";

export { enhance };
export { match };
import { clone, isArray, isFunction, isPrimitive } from "../misc/Utils";

/**
* Create a query for this node graph, matching either the root or leaf nodes
Expand Down Expand Up @@ -68,7 +61,7 @@ class PathBuilderState {
private rootExpression: string;

constructor(private root: any) {
this.isMatch = enhancer.isMatch(root);
this.isMatch = isMatch(root);
this.rootExpression = typeToAddress(root);
}

Expand Down Expand Up @@ -96,7 +89,7 @@ class PathBuilderState {
this.rootExpression +
this.simplePredicates +
this.complexPredicates +
enhancer.customPredicate(this.root),
customPredicate(this.root),
this.isMatch);
}
}
Expand Down Expand Up @@ -180,3 +173,132 @@ function isRelevantPropertyName(id: string): boolean {
id.indexOf("_") !== 0 &&
id.indexOf("$") !== 0;
}

/**
* Mark this object as a match that will be
* returned as a leaf (match node)
* @param a object to mark as a match
*/
export function match(a) {
a.$match = true;
return a;
}

export function isMatch(a) {
return a.$match === true;
}

/**
* Interface mixed into enhanced objects.
*/
export interface Enhanced<T> {

/**
* Add a custom predicate string to this node
*/
withCustomPredicate(predicate: string): EnhancedReturn<T>;

/**
* Match either of these cases
* @param a function to add examples to an object of this type
* @param b function to add examples tp am pbkect of this type
*/
optional(what: (T) => void): EnhancedReturn<T>;

/**
* Specify that we should NOT match whatever state the specified function creates
* @param what what we should not do: Invoke "with" or "add" methods
*/
not(what: (T) => void): EnhancedReturn<T>;

or(a: (T) => void, b: (T) => void): EnhancedReturn<T>;

}

export type EnhancedReturn<T> = T & Enhanced<T>;

/*
Mixin functions to add to nodes to
allow building more powerful queries.
*/

function withCustomPredicate(predicate: string) {
if (!this.$predicate) {
this.$predicate = "";
}
this.$predicate += predicate;
return this;
}

export function customPredicate(a): string {
return a.$predicate ? a.$predicate : "";
}

/*
Our strategy for all these mixed-in methods is the same:
Clone the existing object and run the user's function on it.
The function should create additional predicates.
Then manipulate the returned predicate as necesary.
*/

function optional<T>(what: (T) => void) {
const shallowCopy = clone(this);
what(shallowCopy);
const rawPredicate = dropLeadingType(byExample(shallowCopy).expression);
const optionalPredicate = rawPredicate + "?";
this.withCustomPredicate(optionalPredicate);
return this;
}

function not<T>(what: (T) => void) {
const shallowCopy = clone(this);
what(shallowCopy);
const rawPredicate = dropLeadingType(byExample(shallowCopy).expression);
const nottedPredicate = rawPredicate.replace("[", "[not ");
this.withCustomPredicate(nottedPredicate);
return this;
}

function or<T>(a: (T) => void, b: (T) => void) {
const aCopy = clone(this);
const bCopy = clone(this);
a(aCopy);
b(bCopy);
const aPredicate =
dropLeadingType(byExample(aCopy).expression);
const bPredicate =
dropLeadingType(byExample(bCopy).expression);
const oredPredicate =
aPredicate.replace("]", " or") +
bPredicate.replace("[", " ");
this.withCustomPredicate(oredPredicate);
return this;
}

/**
* Drop the leading type, e.g. Build() from a path expression such as
* Build()[@status='passed']
* Used to extract predicates.
* @param s path expression
*/
function dropLeadingType(s: string): string {
return s.substring(s.indexOf("["));
}

/**
* Decorate a node with appropriate mixin functions
* to add power to query by example.
* @param a node to decorate
*/
export function enhance<T>(node): EnhancedReturn<T> {
// Manually mix in the methods from the Enhanced interface
const optKey = "optional";
node[optKey] = optional;
const withKey = "withCustomPredicate";
node[withKey] = withCustomPredicate;
const notKey = "not";
node[notKey] = not;
const orKey = "or";
node[orKey] = or;
return node;
}

0 comments on commit 7da3009

Please sign in to comment.