From 7da30098afcd601c5204e7aa78b4978ad605a44a Mon Sep 17 00:00:00 2001 From: James Carnegie Date: Fri, 28 Apr 2017 13:14:38 +0100 Subject: [PATCH] Prepare for 1.0.0-m.2 release --- CHANGELOG.md | 9 ++- util/tree/Enhance.ts | 147 ------------------------------------ util/tree/QueryByExample.ts | 142 +++++++++++++++++++++++++++++++--- 3 files changed, 140 insertions(+), 158 deletions(-) delete mode 100644 util/tree/Enhance.ts diff --git a/CHANGELOG.md b/CHANGELOG.md index e1d0aad..48fddf2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,7 +7,13 @@ 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 @@ -15,6 +21,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ### Fixed +- Removed circular references between Enhance.ts and QueryByExample.ts - Properly lint all TypeScript source files ## [1.0.0-m.1] - 2017-04-26 diff --git a/util/tree/Enhance.ts b/util/tree/Enhance.ts deleted file mode 100644 index 59bac1c..0000000 --- a/util/tree/Enhance.ts +++ /dev/null @@ -1,147 +0,0 @@ -/* - * Copyright © 2017 Atomist, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { clone } from "../misc/Utils"; -import * as query from "./QueryByExample"; - -/** - * 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 { - - /** - * Add a custom predicate string to this node - */ - withCustomPredicate(predicate: string): EnhancedReturn; - - /** - * 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; - - /** - * 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; - - or(a: (T) => void, b: (T) => void): EnhancedReturn; - -} - -export type EnhancedReturn = T & Enhanced; - -/* - 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(what: (T) => void) { - const shallowCopy = clone(this); - what(shallowCopy); - const rawPredicate = dropLeadingType(query.byExample(shallowCopy).expression); - const optionalPredicate = rawPredicate + "?"; - this.withCustomPredicate(optionalPredicate); - return this; -} - -function not(what: (T) => void) { - const shallowCopy = clone(this); - what(shallowCopy); - const rawPredicate = dropLeadingType(query.byExample(shallowCopy).expression); - const nottedPredicate = rawPredicate.replace("[", "[not "); - this.withCustomPredicate(nottedPredicate); - return this; -} - -function or(a: (T) => void, b: (T) => void) { - const aCopy = clone(this); - const bCopy = clone(this); - a(aCopy); - b(bCopy); - const aPredicate = - dropLeadingType(query.byExample(aCopy).expression); - const bPredicate = - dropLeadingType(query.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(node): EnhancedReturn { - // 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; -} diff --git a/util/tree/QueryByExample.ts b/util/tree/QueryByExample.ts index 211e393..2401b06 100644 --- a/util/tree/QueryByExample.ts +++ b/util/tree/QueryByExample.ts @@ -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 @@ -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); } @@ -96,7 +89,7 @@ class PathBuilderState { this.rootExpression + this.simplePredicates + this.complexPredicates + - enhancer.customPredicate(this.root), + customPredicate(this.root), this.isMatch); } } @@ -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 { + + /** + * Add a custom predicate string to this node + */ + withCustomPredicate(predicate: string): EnhancedReturn; + + /** + * 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; + + /** + * 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; + + or(a: (T) => void, b: (T) => void): EnhancedReturn; + +} + +export type EnhancedReturn = T & Enhanced; + +/* + 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(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(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(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(node): EnhancedReturn { + // 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; +}