Cycles: move hasCycle function into publicodes (useful for unit tests)

cycles-detection-with-context
Alexandre Hajjar 2020-09-22 20:11:31 +02:00
parent a1bb8bebac
commit 4e30ef98b7
5 changed files with 30 additions and 19 deletions

View File

@ -21,8 +21,7 @@
"i18next-parser": "^1.0.6",
"monaco-editor-webpack-plugin": "^1.9.0",
"workbox-webpack-plugin": "^3.6.0",
"worker-loader": "^2.0.0",
"@dagrejs/graphlib": "^2.1.4"
"worker-loader": "^2.0.0"
},
"dependencies": {
"@babel/runtime": "^7.3.4",

View File

@ -1,23 +1,11 @@
import graphlib from '@dagrejs/graphlib'
import { expect } from 'chai'
import { buildRulesDependencies, parseRules } from 'publicodes'
import { hasCycles } from 'publicodes'
import rules from '../source/rules'
describe('DottedNames graph', () => {
it("shouldn't have cycles", () => {
// debugger
let parsedRules = parseRules(rules)
let ruleDependencies = buildRulesDependencies(parsedRules)
// console.log(ruleDependencies)
let g = new graphlib.Graph()
ruleDependencies.forEach(([ruleDottedName, dependenciesDottedNames]) => {
dependenciesDottedNames.forEach(depDottedName => {
g.setEdge(ruleDottedName, depDottedName)
})
})
const cycles = graphlib.alg.findCycles(g)
let cycles = hasCycles(rules)
expect(
cycles,

View File

@ -18,6 +18,9 @@
"dist/images"
],
"private": false,
"devDependencies": {
"@dagrejs/graphlib": "^2.1.4"
},
"dependencies": {
"classnames": "^2.2.6",
"i18next": "^19.4.4",

View File

@ -4,8 +4,10 @@
*/
import * as R from 'ramda'
import graphlib from '@dagrejs/graphlib'
import { ArrondiExplanation } from './mecanisms/arrondi'
import { ParsedRule, ParsedRules } from './types'
import parseRules from './parseRules'
import { ParsedRule, ParsedRules, Rules } from './types'
type OnOff = 'oui' | 'non'
export function isOnOff(a: string): a is OnOff {
@ -966,7 +968,7 @@ function ruleDepsOfRuleNode<Names extends string>(
)
}
export function buildRulesDependencies<Names extends string>(
function buildRulesDependencies<Names extends string>(
parsedRules: ParsedRules<Names>
): Array<[Names, RuleDependencies<Names>]> {
// This stringPairs thing is necessary because `toPairs` is strictly considering that
@ -984,3 +986,22 @@ export function buildRulesDependencies<Names extends string>(
RuleDependencies<Names>
] => [dottedName, ruleDepsOfRuleNode<Names>(ruleNode)])
}
type GraphNodeRepr = string
type GraphCycles = Array<Array<GraphNodeRepr>>
// [XXX] Rename with cyclicDependencies and split this file in 3 parts
export function hasCycles<Names extends string>(
rawRules: Rules<Names> | string
): GraphCycles {
const parsedRules = parseRules(rawRules)
const ruleDependencies = buildRulesDependencies(parsedRules)
const g = new graphlib.Graph()
ruleDependencies.forEach(([ruleDottedName, dependencies]) => {
dependencies.forEach(([depDottedName, depType]) => {
g.setEdge(ruleDottedName, depDottedName, { type: depType })
})
})
return graphlib.alg.findCycles(g)
}

View File

@ -36,7 +36,7 @@ export type EvaluationOptions = Partial<{
export * from './components'
export { formatValue } from './format'
export { default as translateRules } from './translateRules'
export { buildRulesDependencies } from './cyclesLib'
export { hasCycles } from './cyclesLib'
export * from './types'
export { parseRules }