1// Copyright 2021 The Prometheus Authors 2// Licensed under the Apache License, Version 2.0 (the "License"); 3// you may not use this file except in compliance with the License. 4// You may obtain a copy of the License at 5// 6// http://www.apache.org/licenses/LICENSE-2.0 7// 8// Unless required by applicable law or agreed to in writing, software 9// distributed under the License is distributed on an "AS IS" BASIS, 10// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11// See the License for the specific language governing permissions and 12// limitations under the License. 13 14import { EditorState } from '@codemirror/state'; 15import { SyntaxNode } from '@lezer/common'; 16import { 17 And, 18 BinaryExpr, 19 BinModifiers, 20 GroupingLabel, 21 GroupingLabelList, 22 GroupingLabels, 23 GroupLeft, 24 GroupRight, 25 On, 26 OnOrIgnoring, 27 Or, 28 Unless, 29} from '../grammar/parser.terms'; 30import { VectorMatchCardinality, VectorMatching } from '../types'; 31import { containsAtLeastOneChild, retrieveAllRecursiveNodes } from './path-finder'; 32 33export function buildVectorMatching(state: EditorState, binaryNode: SyntaxNode): VectorMatching | null { 34 if (!binaryNode || binaryNode.type.id !== BinaryExpr) { 35 return null; 36 } 37 const result: VectorMatching = { 38 card: VectorMatchCardinality.CardOneToOne, 39 matchingLabels: [], 40 on: false, 41 include: [], 42 }; 43 const binModifiers = binaryNode.getChild(BinModifiers); 44 if (binModifiers) { 45 const onOrIgnoring = binModifiers.getChild(OnOrIgnoring); 46 if (onOrIgnoring) { 47 result.on = onOrIgnoring.getChild(On) !== null; 48 const labels = retrieveAllRecursiveNodes(onOrIgnoring.getChild(GroupingLabels), GroupingLabelList, GroupingLabel); 49 if (labels.length > 0) { 50 for (const label of labels) { 51 result.matchingLabels.push(state.sliceDoc(label.from, label.to)); 52 } 53 } 54 } 55 56 const groupLeft = binModifiers.getChild(GroupLeft); 57 const groupRight = binModifiers.getChild(GroupRight); 58 if (groupLeft || groupRight) { 59 result.card = groupLeft ? VectorMatchCardinality.CardManyToOne : VectorMatchCardinality.CardOneToMany; 60 const includeLabels = retrieveAllRecursiveNodes(binModifiers.getChild(GroupingLabels), GroupingLabelList, GroupingLabel); 61 if (includeLabels.length > 0) { 62 for (const label of includeLabels) { 63 result.include.push(state.sliceDoc(label.from, label.to)); 64 } 65 } 66 } 67 } 68 69 const isSetOperator = containsAtLeastOneChild(binaryNode, And, Or, Unless); 70 if (isSetOperator && result.card === VectorMatchCardinality.CardOneToOne) { 71 result.card = VectorMatchCardinality.CardManyToMany; 72 } 73 return result; 74} 75