private void registerBlockCompletionInfo(@NotNull String headToken, @NotNull String[] completionParts,
                                             @NotNull String tailToken, @Nullable String tailEndToken, @Nullable String prevCancelToken) {
        if (headToken == null || completionParts == null || tailToken == null) {
            throw new IllegalArgumentException("Illegal block completion info. headToken, completionParts and tailToken are mandatory.");
        }
        
        SQLBlockCompletionInfo info = new SQLBlockCompletionInfo(
                this,
                obtainTokenId(headToken), 
                completionParts, 
                obtainTokenId(tailToken),
                tailEndToken == null ? null : obtainTokenId(tailEndToken),
                // token that shouldn't precede  the block begin token (example: END for block LOOP .. END LOOP)
                prevCancelToken == null ? null : obtainTokenId(prevCancelToken) 
        );
        this.blockCompletionByHeadToken.put(info.getHeadTokenId(), info);
        this.blockCompletionByTailToken.computeIfAbsent(info.getTailTokenId(), n -> new HashMap<>())
           .computeIfAbsent(info.getTailEndTokenId(), n -> new HashSet<>())
           .add(info);
    }
Register block for autoedit containing token at the begin, middle token and one or two tokens at the end (e.g. IF .. THEN .. END IF).
@param headToken is a beginning token of the block.
@param completionParts is an array of strings which should be inserted on autoedit.
Completion part can be a String,
SQLBlockCompletions.ONE_INDENT_COMPLETION_PART - indentation,
SQLBlockCompletions.NEW_LINE_COMPLETION_PART - new line.
@param tailToken - first token of the block end.
@param tailEndToken - last token of the block end.
plugins/org.jkiss.dbeaver.ui.editors.sql/src/org/jkiss/dbeaver/ui/editors/sql/indent/SQLBlockCompletionsCollection.java