/**
   * This method returns a list of completion proposals as ICompletionProposal objects. The
   * proposals are based on the word at the offset in the document where the cursor is positioned.
   * In this implementation, we find the word at the document offset and compare it to our list of
   * SQL reserved words. The list is a subset, of those words that match what the user has entered.
   * For example, the text or proposes the SQL keywords OR and ORDER. The list is returned as an
   * array of completion proposals.
   *
   * @see
   *     org.eclipse.jface.text.contentassist.IContentAssistProcessor#computeCompletionProposals(ITextViewer,
   *     int)
   */
  @Override
  public ICompletionProposal[] computeCompletionProposals(ITextViewer viewer, int documentOffset) {
    this.documentOffset = documentOffset;
    this.activeQuery = null;

    this.wordDetector =
        new SQLWordPartDetector(viewer.getDocument(), editor.getSyntaxManager(), documentOffset);
    final String wordPart = wordDetector.getWordPart();

    if (lookupTemplates) {
      return makeTemplateProposals(viewer, documentOffset, wordPart);
    }

    final List<SQLCompletionProposal> proposals = new ArrayList<>();
    QueryType queryType = null;
    {
      final String prevKeyWord = wordDetector.getPrevKeyWord();
      if (!CommonUtils.isEmpty(prevKeyWord)) {
        if (editor.getSyntaxManager().getDialect().isEntityQueryWord(prevKeyWord)) {
          queryType = QueryType.TABLE;
        } else if (editor.getSyntaxManager().getDialect().isAttributeQueryWord(prevKeyWord)) {
          queryType = QueryType.COLUMN;
        }
      }
    }
    if (queryType != null) {
      if (editor.getDataSource() != null) {
        try {
          final QueryType qt = queryType;
          DBeaverUI.runInProgressService(
              new DBRRunnableWithProgress() {
                @Override
                public void run(DBRProgressMonitor monitor)
                    throws InvocationTargetException, InterruptedException {
                  monitor.beginTask("Seeking for completion proposals", 1);
                  try {
                    monitor.subTask("Make structure proposals");
                    makeStructureProposals(monitor, proposals, wordPart, qt);
                  } finally {
                    monitor.done();
                  }
                }
              });
        } catch (InvocationTargetException e) {
          log.warn("Error while seeking for structure proposals", e.getTargetException());
        } catch (InterruptedException e) {
          // interrupted - do nothing
        }
      }
    }

    if (proposals.isEmpty() || !wordPart.isEmpty()) {
      // Keyword assist
      List<String> matchedKeywords =
          editor.getSyntaxManager().getDialect().getMatchedKeywords(wordPart);
      for (String keyWord : matchedKeywords) {
        DBPKeywordType keywordType = editor.getSyntaxManager().getDialect().getKeywordType(keyWord);
        if (keywordType != null) {
          proposals.add(
              createCompletionProposal(
                  keyWord, keyWord, keyWord + " (" + keywordType.name() + ")", null, false, null));
        }
      }
    }

    // Remove duplications
    for (int i = 0; i < proposals.size(); i++) {
      SQLCompletionProposal proposal = proposals.get(i);
      for (int j = i + 1; j < proposals.size(); ) {
        SQLCompletionProposal proposal2 = proposals.get(j);
        if (proposal.getDisplayString().equals(proposal2.getDisplayString())) {
          proposals.remove(j);
        } else {
          j++;
        }
      }
    }
    DBSObject selectedObject = getSelectedObject(editor.getDataSource());
    boolean hideDups =
        getPreferences().getBoolean(SQLPreferenceConstants.HIDE_DUPLICATE_PROPOSALS)
            && selectedObject != null;
    if (hideDups) {
      for (int i = 0; i < proposals.size(); i++) {
        SQLCompletionProposal proposal = proposals.get(i);
        for (int j = 0; j < proposals.size(); ) {
          SQLCompletionProposal proposal2 = proposals.get(j);
          if (i != j
              && proposal.hasStructObject()
              && proposal2.hasStructObject()
              && CommonUtils.equalObjects(
                  proposal.getObject().getName(), proposal2.getObject().getName())
              && proposal.getObjectContainer() == selectedObject) {
            proposals.remove(j);
          } else {
            j++;
          }
        }
      }
    }

    if (hideDups) {
      // Remove duplicates from non-active schema

      if (selectedObject instanceof DBSObjectContainer) {
        // List<ICompletionProposal>
      }
    }
    return proposals.toArray(new ICompletionProposal[proposals.size()]);
  }