private List<?> computeProposalsWithJobs(
        @NotNull SQLCompletionRequest request,
        @NotNull Position completionRequestPosition,
        @NotNull List<Supplier<ProposalsComputationJobHolder>> completionJobSuppliers
    ) {
        List<ProposalsComputationJobHolder> completionJobs = completionJobSuppliers.stream()
            .map(Supplier::get).collect(Collectors.toList()); // modifiable list!
        boolean hasRunningJobs = true;
        while (hasRunningJobs) {
            // wait for jobs to run asynchronously
            completionJobs.forEach(j -> UIUtils.waitJobCompletion(j.job));
            hasRunningJobs = false;
            // if any job was cancelled while running in background, break the whole proposals computation logic
            if (completionJobs.stream().anyMatch(j -> j.job.isCanceled())) {
                return Collections.emptyList();
            } else {
                // all the jobs succeed, validate if the result is applicable
                int currentOffset = completionRequestPosition.getOffset();
                for (int i = 0; i < completionJobs.size(); i++) {
                    Integer origin = completionJobs.get(i).getProposalsOriginOffset();
                    if (origin != null) {
                        ProposalsJobResultStatus jobResultStatus = evaluateJobResult(request, origin, currentOffset);
                        switch (jobResultStatus) {
                            case VALID: // do nothing, all proposals are ok
                            case PARTIALLY_VALID: // do nothing, proposals will be filtered with validation when supported
                                break;
                            case INVALID: // job restart required
                                completionJobs.set(i, completionJobSuppliers.get(i).get());
                                hasRunningJobs = true;
                                break;
                            case ABORT:
                            default:
                                return Collections.emptyList();
                        }
                    }
                }
            }
        }
        return completionJobs.stream().flatMap(j -> j.getProposals().stream()).toList();
    }
The SQL content assist processor. This content assist processor proposes text
completions and computes context information for a SQL content type.
plugins/org.jkiss.dbeaver.ui.editors.sql/src/org/jkiss/dbeaver/ui/editors/sql/syntax/SQLCompletionProcessor.java