UNPKG

typir

Version:

General purpose type checking library

98 lines 4.87 kB
/****************************************************************************** * Copyright 2025 TypeFox GmbH * This program and the accompanying materials are made available under the * terms of the MIT License, which is available in the project root. ******************************************************************************/ export class DefaultGraphAlgorithms { constructor(services) { this.graph = services.infrastructure.Graph; } collectReachableTypes(from, $relations, filterEdges) { const result = new Set(); const remainingToCheck = [from]; while (remainingToCheck.length > 0) { const current = remainingToCheck.pop(); const outgoingEdges = $relations.flatMap(r => current.getOutgoingEdges(r)); for (const edge of outgoingEdges) { if (edge.cachingInformation === 'LINK_EXISTS' && (filterEdges === undefined || filterEdges(edge))) { if (result.has(edge.to)) { // already checked } else { result.add(edge.to); // this type is reachable remainingToCheck.push(edge.to); // check it for recursive conversions } } } } return result; } existsEdgePath(from, to, $relations, filterEdges) { const visited = new Set(); const stack = [from]; while (stack.length > 0) { const current = stack.pop(); visited.add(current); const outgoingEdges = $relations.flatMap(r => current.getOutgoingEdges(r)); for (const edge of outgoingEdges) { if (edge.cachingInformation === 'LINK_EXISTS' && (filterEdges === undefined || filterEdges(edge))) { if (edge.to === to) { /* It was possible to reach our goal type using this path. * Base case that also catches the case in which start and end are the same * (is there a cycle?). Therefore it is allowed to have been "visited". * True will only be returned if there is a real path (cycle) made up of edges */ return true; } if (!visited.has(edge.to)) { /* The target node of this edge has not been visited before and is also not our goal node * Add it to the stack and investigate this path later. */ stack.push(edge.to); } } } } // Fall through means that we could not reach the goal type return false; } getEdgePath(from, to, $relations, filterEdges) { const visited = new Map(); // the edge from the parent to the current node visited.set(from, undefined); const stack = [from]; while (stack.length > 0) { const current = stack.pop(); const outgoingEdges = $relations.flatMap(r => current.getOutgoingEdges(r)); for (const edge of outgoingEdges) { if (edge.cachingInformation === 'LINK_EXISTS' && (filterEdges === undefined || filterEdges(edge))) { if (edge.to === to) { /* It was possible to reach our goal type using this path. * Base case that also catches the case in which start and end are the same * (is there a cycle?). Therefore it is allowed to have been "visited". * True will only be returned if there is a real path (cycle) made up of edges */ const result = [edge]; // collect the path of used edges, from "to" back to "from" let backNode = edge.from; while (backNode !== from) { const backEdge = visited.get(backNode); result.unshift(backEdge); backNode = backEdge.from; } return result; } if (!visited.has(edge.to)) { /* The target node of this edge has not been visited before and is also not our goal node * Add it to the stack and investigate this path later. */ stack.push(edge.to); visited.set(edge.to, edge); } } } } // Fall through means that we could not reach the goal type return []; } } //# sourceMappingURL=graph-algorithms.js.map