Include parens in tree FilterPreview

pull/10616/head
Andrew Watkins 2018-05-09 16:03:47 -07:00
parent 2783582189
commit 0b22a6fb13
3 changed files with 94 additions and 13 deletions

View File

@ -63,27 +63,50 @@ export default class Walker {
return this.inOrder(tree)
}
private inOrder = (node): InOrderNode[] => {
private hasParen = (parent, child): boolean => {
if (parent.operator && parent.operator.toLowerCase() === 'and') {
// for mathematical operations:
// if parent and child have operators
// // return child precedence < parent precedence
// return false
if (
child.type === 'LogicalExpression' &&
child.operator.toLowerCase() === 'or'
) {
return true
}
}
return false
}
private inOrder = (node, paren = false): InOrderNode[] => {
let results = []
if (node) {
results = [...results, ...this.inOrder(node.left)]
if (paren) {
results = [...results, {source: '(', type: 'OpenParen'}]
}
const isLeftParen = this.hasParen(node, node.left)
results = [...results, ...this.inOrder(node.left, isLeftParen)]
if (
node.type === 'MemberExpression' ||
node.type === 'ObjectExpression'
) {
const {location, object, property} = node
const {name} = object
const {value, type} = property
const {name, type} = property
const {source} = location
results = [
...results,
{
source,
object: {name, type: object.type},
property: {value, type},
object: {name: object.name, type: object.type},
property: {name, type},
type: node.type,
paren,
},
]
}
@ -93,14 +116,26 @@ export default class Walker {
}
if (node.name) {
results = [...results, {type: node.type, source: node.location.source}]
results = [
...results,
{type: node.type, source: node.location.source, paren},
]
}
if (node.value) {
results = [...results, {type: node.type, source: node.location.source}]
results = [
...results,
{type: node.type, source: node.location.source, paren},
]
}
results = [...results, ...this.inOrder(node.right)]
const isRightParen = this.hasParen(node, node.right)
results = [...results, ...this.inOrder(node.right, isRightParen)]
if (paren) {
results = [...results, {source: ')', type: 'CloseParen'}]
}
}
return results

View File

@ -9,7 +9,53 @@ interface Props {
class FilterPreview extends PureComponent<Props> {
public render() {
return this.props.nodes.map((n, i) => <div key={i}>{n.source}</div>)
return (
<div style={{display: 'flex'}}>
{this.props.nodes.map((n, i) => <FilterPreviewNode node={n} key={i} />)}
</div>
)
}
}
interface FilterPreviewNodeProps {
node: FilterNode
}
/* tslint:disable */
class FilterPreviewNode extends PureComponent<FilterPreviewNodeProps> {
public render() {
const {node} = this.props
return <div className={this.className}>{node.source}</div>
}
private get className(): string {
const {type} = this.props.node
switch (type) {
case 'ObjectExpression':
case 'MemberExpression': {
return 'ifql-filter--expression'
}
case 'OpenParen':
case 'CloseParen': {
return 'ifql-filter--paren'
}
case 'NumberLiteral': {
return 'variable-value--number'
}
case 'BooleanLiteral': {
return 'variable-value--boolean'
}
case 'StringLiteral': {
return 'variable-value--string'
}
case 'Operator': {
return 'ifql-filter--operator'
}
default: {
return ''
}
}
}
}

View File

@ -39,9 +39,9 @@ export class IFQLPage extends PureComponent<Props, State> {
ast: null,
suggestions: [],
script: `from(db:"foo")
|> filter(fn: (r) => r._measurement =="cpu" AND
r["_field"] == "usage_system" AND
r["service"] == "app-server")`,
|> filter(fn: (r) =>
(r.a == "one" OR r.b == "two") AND
(r.c == "three" OR r.d == "four"))`,
}
}