# COV_EXCL_START

const PRECOMPILE_ERRORS = Ref(false)

macro warnpcfail(ex::Expr)
    modl = __module__
    file = __source__.file === nothing ? "?" : String(__source__.file)
    line = __source__.line

    quote

        $(esc(ex)) || begin
            @warn """precompile directive

                $($(Expr(:quote, ex)))

            failed. Please report an issue in $($modl) (after checking for duplicates) or remove this directive.
            """ _file=$file _line=$line

            $PRECOMPILE_ERRORS[] = true
        end
    end
end

function _precompile_()
    ccall(:jl_generating_output, Cint, ()) == 1 || return nothing

    @warnpcfail precompile(Tuple{TaskThunk})
    @warnpcfail precompile(Tuple{typeof(wait_changed), String})
    @warnpcfail precompile(Tuple{typeof(watch_package), PkgId})
    @warnpcfail precompile(Tuple{typeof(watch_includes), Module, String})
    @warnpcfail precompile(Tuple{typeof(watch_manifest), String})
    @warnpcfail precompile(Tuple{typeof(revise_dir_queued), String})
    @warnpcfail precompile(Tuple{typeof(revise_file_queued), PkgData, String})
    @warnpcfail precompile(Tuple{typeof(init_watching), PkgData, Vector{String}})
    @warnpcfail precompile(Tuple{typeof(add_revise_deps)})
    @warnpcfail precompile(Tuple{typeof(watch_package_callback), PkgId})

    @warnpcfail precompile(Tuple{typeof(revise)})
    @warnpcfail precompile(Tuple{typeof(revise_first), Expr})
    @warnpcfail precompile(Tuple{typeof(includet), String})
    @warnpcfail precompile(Tuple{typeof(track), Module, String})
    # setindex! doesn't fully precompile, but it's still beneficial to do it
    # (it shaves off a bit of the time)
    # See https://github.com/JuliaLang/julia/pull/31466
    @warnpcfail precompile(Tuple{typeof(setindex!), ExprsInfos, Nothing, RelocatableExpr})
    @warnpcfail precompile(Tuple{typeof(setindex!), ExprsInfos, Vector{Any}, RelocatableExpr})
    @warnpcfail precompile(Tuple{typeof(setindex!), ModuleExprsInfos, ExprsInfos, Module})
    @warnpcfail precompile(Tuple{typeof(setindex!), Dict{PkgId,PkgData}, PkgData, PkgId})
    @warnpcfail precompile(Tuple{Type{WatchList}})
    @warnpcfail precompile(Tuple{typeof(setindex!), Dict{String,WatchList}, WatchList, String})

    MI = ExInfo
    @warnpcfail precompile(Tuple{typeof(minimal_evaluation!), Any, Module, Core.CodeInfo, Symbol})
    @warnpcfail precompile(Tuple{typeof(methods_by_execution!), Compiled, MI, Module, Expr})
    @warnpcfail precompile(Tuple{typeof(_methods_by_execution!), Compiled, MI, Frame, Vector{Bool}})
    @warnpcfail precompile(Tuple{typeof(Core.kwfunc(methods_by_execution!)),
                             NamedTuple{(:mode,),Tuple{Symbol}},
                             typeof(methods_by_execution!), Compiled, MI, Module, Expr})
    @warnpcfail precompile(Tuple{typeof(Core.kwfunc(methods_by_execution!)),
                             NamedTuple{(:skip_include,),Tuple{Bool}},
                             typeof(methods_by_execution!), Compiled, MI, Module, Expr})
    @warnpcfail precompile(Tuple{typeof(Core.kwfunc(methods_by_execution!)),
                             NamedTuple{(:mode, :skip_include),Tuple{Symbol,Bool}},
                             typeof(methods_by_execution!), Compiled, MI, Module, Expr})
    @warnpcfail precompile(Tuple{typeof(Core.kwfunc(_methods_by_execution!)),
                             NamedTuple{(:mode,),Tuple{Symbol}},
                             typeof(_methods_by_execution!), Compiled, MI, Frame, Vector{Bool}})
    @warnpcfail precompile(Tuple{typeof(Core.kwfunc(_methods_by_execution!)),
                             NamedTuple{(:mode, :skip_include),Tuple{Symbol,Bool}},
                             typeof(_methods_by_execution!), Compiled, MI, Frame, Vector{Bool}})

    mex = which(methods_by_execution!, (Compiled, MI, Module, Expr))
    mbody = bodymethod(mex)
    # use `typeof(pairs(NamedTuple()))` here since it actually differs between Julia versions
    @warnpcfail precompile(Tuple{mbody.sig.parameters[1], Symbol, Bool, Bool, typeof(pairs(NamedTuple())), typeof(methods_by_execution!), Compiled, MI, Module, Expr})
    if VERSION >= v"1.12-"
        @warnpcfail precompile(Tuple{mbody.sig.parameters[1], Symbol, Bool, Bool, Iterators.Pairs{Symbol,Bool,Nothing,NamedTuple{(:skip_include,),Tuple{Bool}}}, typeof(methods_by_execution!), Compiled, MI, Module, Expr})
    else
        @warnpcfail precompile(Tuple{mbody.sig.parameters[1], Symbol, Bool, Bool, Iterators.Pairs{Symbol,Bool,Tuple{Symbol},NamedTuple{(:skip_include,),Tuple{Bool}}}, typeof(methods_by_execution!), Compiled, MI, Module, Expr})
    end
    mfr = which(_methods_by_execution!, (Compiled, MI, Frame, Vector{Bool}))
    mbody = bodymethod(mfr)
    @warnpcfail precompile(Tuple{mbody.sig.parameters[1], Symbol, Bool, typeof(_methods_by_execution!), Compiled, MI, Frame, Vector{Bool}})

    @warnpcfail precompile(Tuple{typeof(get_def), Method})
    @warnpcfail precompile(Tuple{typeof(parse_pkg_files), PkgId})
    if isdefined(Revise, :filter_valid_cachefiles)
        @warnpcfail precompile(Tuple{typeof(filter_valid_cachefiles), String, Vector{String}})
    end
    @warnpcfail precompile(Tuple{typeof(Revise.iswritable), String})
    @warnpcfail precompile(Tuple{typeof(Revise.active_repl_backend_available)})
    @warnpcfail precompile(Tuple{typeof(wait_for_repl_backend)})
    @warnpcfail precompile(Tuple{typeof(pkg_fileinfo), PkgId})
    @warnpcfail precompile(Tuple{typeof(push!), WatchList, Pair{String,PkgId}})
    @warnpcfail precompile(Tuple{typeof(pushex!), ExprsInfos, Expr})
    @warnpcfail precompile(Tuple{Type{ModuleExprsInfos}, Module})
    @warnpcfail precompile(Tuple{Type{FileInfo}, Module, String})
    @warnpcfail precompile(Tuple{Type{PkgData}, PkgId})
    @warnpcfail precompile(Tuple{typeof(Base._deleteat!), Vector{Tuple{Module,String,Float64}}, Vector{Int}})
    @warnpcfail precompile(Tuple{typeof(add_require), String, Module, String, String, Expr})
    @warnpcfail precompile(Tuple{Core.kwftype(typeof(maybe_add_includes_to_pkgdata!)),NamedTuple{(:eval_now,), Tuple{Bool}},typeof(maybe_add_includes_to_pkgdata!),PkgData,String,Vector{Tuple{Module, Function, String}}})

    for TT in (Tuple{Module,Expr}, Tuple{DataType,MethodSummary})
        @warnpcfail precompile(Tuple{Core.kwftype(typeof(Base.CoreLogging.handle_message)),NamedTuple{(:time, :deltainfo), Tuple{Float64, TT}},typeof(Base.CoreLogging.handle_message),ReviseLogger,LogLevel,String,Module,String,Symbol,String,Int})
    end

    if get(ENV, "REVISE_PRECOMPILE_ERROR", "false") == "true" && PRECOMPILE_ERRORS[]
        error("Precompile statements failed. See output above for details")
    end

    return nothing
end
# COV_EXCL_STOP
