// external routines for context verification

        /// <summary>
        /// Given the line number of the lines that contain tokens that (possibly) have been modified,
        /// checks which callable declaration they can potentially belong to and returns the fully qualified name of those callables.
        /// </summary>
        internal static IEnumerable <(Range, QsQualifiedName)> CallablesWithContentModifications(this FileContentManager file, IEnumerable <int> changedLines)
        {
            var lastInFile = file.LastToken()?.GetFragment()?.Range?.End ?? file.End();
            var callables  = file.GetCallableDeclarations().Select(tuple => // these are sorted according to their line number
            {
                var ns = file.TryGetNamespaceAt(tuple.Item2.Start);
                QsCompilerError.Verify(ns != null, "namespace for callable declaration should not be null"); // invalid namespace names default to an unknown namespace name, but remain included in the compilation
                return(tuple.Item2.Start, new QsQualifiedName(ns, tuple.Item1));
            }).ToList();

            // NOTE: The range of modifications that has to trigger an update of the syntax tree for a callable
            // does need to go up to and include modifications to the line containing the next callable!
            // Otherwise inserting a callable declaration in the middle of an existing callable does not trigger the right behavior!
            (Range, QsQualifiedName) TypeCheckingRange((Position, QsQualifiedName) lastPreceding, IEnumerable <(Position, QsQualifiedName)> next)
            {
                var callableStart = lastPreceding.Item1;
                var callableEnd   = next.Any() ? next.First().Item1 : lastInFile;

                return(Range.Create(callableStart, callableEnd), lastPreceding.Item2);
            }

            foreach (var lineNr in changedLines)
            {
                bool Precedes((Position, QsQualifiedName) tuple) => tuple.Item1.Line < lineNr;

                var preceding = callables.TakeWhile(Precedes);
                var following = callables.SkipWhile(Precedes);

                if (preceding.Any())
                {
                    yield return(TypeCheckingRange(preceding.Last(), following));
                }
                if (following.Any() && following.First().Start.Line == lineNr)
                {
                    yield return(TypeCheckingRange(following.First(), following.Skip(1)));
                }
            }
        }
 /// <summary>
 /// Returns a function that returns true if a given fragment does not overlap with the specified range.
 /// </summary>
 internal static Func <CodeFragment, bool> NotOverlappingWith(Range relRange) => token =>
 token.IsWithinRange(Range.Create(Position.Zero, relRange.Start)) ||
 TokensAfter(relRange.End)(token);