/**
  * Returns the valid Java identifier in a document immediately before the given offset.
  *
  * @param document the document
  * @param offset the offset at which to start looking
  * @return the Java identifier preceding this location or a blank string if none
  */
 private String lastWord(IDocument document, int offset) {
   try {
     for (int n = offset - 1; n >= 0; n--) {
       char c = document.getChar(n);
       if (!Character.isJavaIdentifierPart(c)) {
         return document.get(n + 1, offset - n - 1);
       }
     }
     return document.get(0, offset);
   } catch (BadLocationException e) {
     Activator.log(e);
   }
   return ""; //$NON-NLS-1$
 }
  @Override
  public ICompletionProposal[] computeCompletionProposals(ITextViewer viewer, int offset) {
    try {
      IDocument document = viewer.getDocument();
      ArrayList<ICompletionProposal> result = new ArrayList<>();

      // Search the list of keywords (case-insensitive)
      String prefix = lastWord(document, offset).toLowerCase(Locale.ROOT);
      for (QtProjectFileKeyword keyword : QtProjectFileKeyword.values()) {
        if (prefix.isEmpty() || keyword.getKeyword().toLowerCase(Locale.ROOT).startsWith(prefix)) {
          result.add(
              new CompletionProposal(
                  keyword.getKeyword(),
                  offset - prefix.length(),
                  prefix.length(),
                  keyword.getKeyword().length()));
        }
      }
      return result.toArray(new ICompletionProposal[result.size()]);
    } catch (Exception e) {
      Activator.log(e);
      return NO_COMPLETIONS;
    }
  }