private void makeStructureProposals(
      DBRProgressMonitor monitor, DBPDataSource dataSource, List<SQLCompletionProposal> proposals) {
    final DBSObjectContainer rootContainer =
        DBUtils.getAdapter(DBSObjectContainer.class, dataSource);
    if (rootContainer == null) {
      return;
    }
    DBSObjectContainer selectedContainer = null;
    {
      DBSObject selectedObject = getSelectedObject(dataSource);
      if (selectedObject != null) {
        selectedContainer = DBUtils.getAdapter(DBSObjectContainer.class, selectedObject);
      }
    }

    DBSObjectContainer sc = rootContainer;
    DBSObject childObject = sc;
    List<String> tokens = wordDetector.splitWordPart();

    String lastToken = null;
    for (int i = 0; i < tokens.size(); i++) {
      String token = tokens.get(i);
      if (i == tokens.size() - 1 && !wordDetector.getWordPart().endsWith(".")) {
        lastToken = token;
        break;
      }
      if (sc == null) {
        break;
      }
      // Get next structure container
      try {
        String objectName = DBObjectNameCaseTransformer.transformName(dataSource, token);
        childObject = sc.getChild(monitor, objectName);
        if (childObject == null && i == 0 && selectedContainer != null) {
          // Probably it is from selected object, let's try it
          childObject = selectedContainer.getChild(monitor, objectName);
          if (childObject != null) {
            sc = selectedContainer;
          }
        }
        if (childObject == null) {
          if (i == 0) {
            // Assume it's a table alias ?
            childObject = this.getTableFromAlias(monitor, sc, token);
            if (childObject == null) {
              DBSStructureAssistant structureAssistant =
                  DBUtils.getAdapter(DBSStructureAssistant.class, sc);
              if (structureAssistant != null) {
                Collection<DBSObjectReference> references =
                    structureAssistant.findObjectsByMask(
                        monitor,
                        null,
                        structureAssistant.getAutoCompleteObjectTypes(),
                        wordDetector.removeQuotes(token),
                        wordDetector.isQuoted(token),
                        2);
                if (!references.isEmpty()) {
                  childObject = references.iterator().next().resolveObject(monitor);
                }
              }
            }
          } else {
            // Path element not found. Damn - can't do anything.
            return;
          }
        }

        if (childObject instanceof DBSObjectContainer) {
          sc = (DBSObjectContainer) childObject;
        } else {
          sc = null;
        }
      } catch (DBException e) {
        log.error(e);
        return;
      }
    }
    if (childObject == null) {
      return;
    }
    if (lastToken == null) {
      // Get all children objects as proposals
      makeProposalsFromChildren(monitor, childObject, null, proposals);
    } else {
      // Get matched children
      makeProposalsFromChildren(monitor, childObject, lastToken, proposals);
      if (proposals.isEmpty() || tokens.size() == 1) {
        // At last - try to find child tables by pattern
        DBSStructureAssistant structureAssistant = null;
        for (DBSObject object = childObject; object != null; object = object.getParentObject()) {
          structureAssistant = DBUtils.getAdapter(DBSStructureAssistant.class, object);
          if (structureAssistant != null) {
            break;
          }
        }
        if (structureAssistant != null) {
          makeProposalsFromAssistant(monitor, structureAssistant, sc, lastToken, proposals);
        }
      }
    }
  }
  /**
   * 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()]);
  }