private Collection<ICompletionProposal> getNavigationProposals(IDocument doc, int offset) {
   String navPrefix = navigationPrefixFinder.getPrefix(doc, offset);
   try {
     if (navPrefix != null) {
       int navOffset =
           offset - navPrefix.length() - 1; // offset of 'nav' operator char (i.e. '.' or ']').
       navPrefix = fuzzySearchPrefix.getPrefix(doc, navOffset);
       if (navPrefix != null && !navPrefix.isEmpty()) {
         PropertyInfo prop = findLongestValidProperty(getIndex(), navPrefix);
         if (prop != null) {
           int regionStart = navOffset - navPrefix.length();
           PropertyNavigator navigator =
               new PropertyNavigator(doc, null, typeUtil, region(regionStart, navOffset));
           Type type =
               navigator.navigate(
                   regionStart + prop.getId().length(), TypeParser.parse(prop.getType()));
           if (type != null) {
             return getNavigationProposals(doc, type, navOffset, offset);
           }
         }
       }
     }
   } catch (Exception e) {
     BootActivator.log(e);
   }
   return Collections.emptyList();
 }
 protected Collection<ICompletionProposal> getFuzzyCompletions(
     final IDocument doc, final int offset) {
   final String prefix = fuzzySearchPrefix.getPrefix(doc, offset);
   if (prefix != null) {
     Collection<Match<PropertyInfo>> matches = findMatches(prefix);
     if (matches != null && !matches.isEmpty()) {
       ArrayList<ICompletionProposal> proposals =
           new ArrayList<ICompletionProposal>(matches.size());
       for (final Match<PropertyInfo> match : matches) {
         ProposalApplier edits =
             new LazyProposalApplier() {
               @Override
               protected ProposalApplier create() throws Exception {
                 Type type = TypeParser.parse(match.data.getType());
                 DocumentEdits edits = new DocumentEdits(doc);
                 edits.delete(offset - prefix.length(), offset);
                 edits.insert(offset, match.data.getId() + propertyCompletionPostfix(type));
                 return edits;
               }
             };
         proposals.add(completionFactory.property(doc, edits, match, typeUtil));
       }
       return proposals;
     }
   }
   return Collections.emptyList();
 }
 private Collection<ICompletionProposal> getValueCompletions(
     IDocument doc, int offset, ITypedRegion valuePartition) {
   int regionStart = valuePartition.getOffset();
   int startOfValue = findValueStart(doc, regionStart);
   try {
     String valuePrefix;
     if (startOfValue >= 0 && startOfValue < offset) {
       valuePrefix = doc.get(startOfValue, offset - startOfValue);
     } else {
       startOfValue = offset;
       valuePrefix = "";
     }
     EnumCaseMode caseMode = caseMode(valuePrefix);
     String propertyName =
         fuzzySearchPrefix.getPrefix(
             doc, regionStart); // note: no need to skip whitespace backwards.
     // because value partition includes whitespace around the assignment
     if (propertyName != null) {
       Type type = getValueType(propertyName);
       String[] valueCompletions = typeUtil.getAllowedValues(type, caseMode);
       if (valueCompletions != null && valueCompletions.length > 0) {
         ArrayList<ICompletionProposal> proposals = new ArrayList<ICompletionProposal>();
         for (int i = 0; i < valueCompletions.length; i++) {
           String valueCandidate = valueCompletions[i];
           double score = FuzzyMatcher.matchScore(valuePrefix, valueCandidate);
           if (score != 0) {
             DocumentEdits edits = new DocumentEdits(doc);
             edits.delete(startOfValue, offset);
             edits.insert(offset, valueCandidate);
             proposals.add(
                 completionFactory.valueProposal(valueCandidate, type, score, edits)
                 // new ValueProposal(startOfValue, valuePrefix, valueCandidate, i)
                 );
           }
         }
         return proposals;
       }
     }
   } catch (Exception e) {
     SpringPropertiesEditorPlugin.log(e);
   }
   return Collections.emptyList();
 }