/// <summary>
        /// Returns the position and the kind of the closest specialization preceding the given position,
        /// and the name of the callable it belongs to as well as its position as Nullable.
        /// Returns null if the given file or position is null, or if no preceding callable can be found (e.g. because the callable name is invalid).
        /// If a callable name but no specializations (preceding or otherwise) within that callable can be found,
        /// assumes that the correct specialization is an auto-inserted default body,
        /// and returns QsBody as well as the start position of the callable declaration along with the callable name and its position.
        /// If a callable name as well as existing specializations can be found, but no specialization precedes the given position,
        /// returns null for the specialization kind as well as for its position.
        /// </summary>
        public static ((string, Position), (QsSpecializationKind?, Position?))? TryGetClosestSpecialization(
            this FileContentManager file, Position pos)
        {
            QsSpecializationKind?GetSpecializationKind(CodeFragment fragment)
            {
                var specDecl = fragment.Kind.DeclaredSpecialization();

                if (specDecl.IsNull)
                {
                    return(null);
                }
                var((kind, gen), typeArgs) = specDecl.Item;  // note: if we want to support type specializations we need to compute the signature of the spec to find the right one
                return(kind);
            }

            if (file == null || pos == null || !file.ContainsPosition(pos))
            {
                return(null);
            }
            file.SyncRoot.EnterReadLock();
            try
            {
                var declarations  = file.CallableDeclarationTokens();
                var precedingDecl = declarations.TakeWhile(tIndex => tIndex.GetFragment().Range.Start < pos);
                if (!precedingDecl.Any())
                {
                    return(null);
                }

                var closestCallable  = precedingDecl.Last();
                var callablePosition = closestCallable.GetFragment().Range.Start;
                var callableName     = closestCallable.GetFragment().Kind.DeclaredCallableName(null);
                if (callableName == null)
                {
                    return(null);
                }

                var specializations = FileHeader.FilterCallableSpecializations(closestCallable.GetChildren(deep: false).Select(tIndex => tIndex.GetFragment()));
                var precedingSpec   = specializations.TakeWhile(fragment => fragment.Range.Start < pos);
                var lastPreceding   = precedingSpec.Any() ? precedingSpec.Last() : null;

                if (specializations.Any() && lastPreceding == null)
                {
                    // the given position is within a callable declaration
                    return((callableName, callablePosition), (null, null));
                }
                return(lastPreceding == null
                    ? ((callableName, callablePosition), (QsSpecializationKind.QsBody, callablePosition))
                    : ((callableName, callablePosition), (GetSpecializationKind(lastPreceding), lastPreceding.Range.Start)));
            }
            finally
            {
                file.SyncRoot.ExitReadLock();
            }
        }