/** Override to improve matching accuracy */
  @Override
  public ICompletionProposal[] computeCompletionProposals(ITextViewer viewer, int offset) {

    ITextSelection selection = (ITextSelection) viewer.getSelectionProvider().getSelection();

    // adjust offset to end of normalized selection
    if (selection.getOffset() == offset) {
      offset = selection.getOffset() + selection.getLength();
    }

    String prefix = extractPrefix(viewer, offset);
    Region region = new Region(offset - prefix.length(), prefix.length());
    TemplateContext context = createContext(viewer, region);
    if (context == null) {
      return new ICompletionProposal[0];
    }
    Region selectionRegion = new Region(selection.getOffset(), selection.getLength());
    TemplateContext selectionContext = createContext(viewer, selectionRegion);

    int lineOffset = 0;
    try {
      IRegion lineInformationOfOffset = viewer.getDocument().getLineInformationOfOffset(offset);
      lineOffset = offset - lineInformationOfOffset.getOffset();
    } catch (BadLocationException e1) {
      // ignore
    }

    String selectionText = selection.getText();
    context.setVariable("selection", selectionText); // $NON-NLS-1$
    selectionContext.setVariable("selection", selectionText); // $NON-NLS-1$
    context.setVariable("text", selectionText); // $NON-NLS-1$
    selectionContext.setVariable("text", selectionText); // $NON-NLS-1$

    Template[] templates = getTemplates(context.getContextType().getId());

    List<ICompletionProposal> matches = new ArrayList<>(templates.length);
    for (Template template : templates) {
      try {
        context.getContextType().validate(template.getPattern());
      } catch (TemplateException e) {
        continue;
      }
      if (!template.matches(prefix, context.getContextType().getId())) {
        continue;
      }
      boolean selectionBasedMatch = isSelectionBasedMatch(template, context);
      if (template.getName().startsWith(prefix) || selectionBasedMatch) {

        int relevance = getRelevance(template, lineOffset, prefix);
        if (selectionBasedMatch) {
          matches.add(
              createProposal(template, selectionContext, (IRegion) selectionRegion, relevance));
        } else {
          matches.add(createProposal(template, context, (IRegion) region, relevance));
        }
      }
    }

    Collections.sort(matches, proposalComparator);

    return matches.toArray(new ICompletionProposal[matches.size()]);
  }