private void reportDuplicateKeys(Set<Object> duplicateKeys) {
    if (duplicateKeys.size() == 0) return;

    FileEntry groupElement =
        new FileEntry(fPropertiesFile, NLSSearchMessages.NLSSearchResultCollector_duplicateKeys);
    Iterator<Object> iter = duplicateKeys.iterator();
    while (iter.hasNext()) {
      String propertyName = (String) iter.next();
      addMatch(groupElement, propertyName);
    }
    fResult.addFileEntryGroup(groupElement);
  }
  /*
   * @see org.eclipse.jdt.core.search.SearchRequestor#acceptSearchMatch(org.eclipse.jdt.core.search.SearchMatch)
   */
  @Override
  public void acceptSearchMatch(SearchMatch match) throws CoreException {
    if (match.getAccuracy() == SearchMatch.A_INACCURATE) return;

    int offset = match.getOffset();
    int length = match.getLength();
    if (offset == -1 || length == -1) return;

    if (!(match.getElement() instanceof IJavaElement)) return;
    IJavaElement javaElement = (IJavaElement) match.getElement();

    // ignore matches in import declarations:
    if (javaElement.getElementType() == IJavaElement.IMPORT_DECLARATION) return;
    if (javaElement.getElementType() == IJavaElement.CLASS_FILE)
      return; // matches in import statements of class files
    if (javaElement.getElementType() == IJavaElement.TYPE)
      return; // classes extending the accessor class and workaround for bug 61286

    // heuristic: ignore matches in resource bundle name field:
    if (javaElement.getElementType() == IJavaElement.FIELD) {
      IField field = (IField) javaElement;
      String source = field.getSource();
      if (source != null && fgGetClassNameMatcher.match(source)) return;
    }

    if (javaElement instanceof ISourceReference) {
      String source = ((ISourceReference) javaElement).getSource();
      if (source != null) {
        if (source.indexOf("NLS.initializeMessages") != -1) // $NON-NLS-1$
        return;
      }
    }

    // found reference to NLS Wrapper - now check if the key is there:
    Position mutableKeyPosition = new Position(offset, length);
    // TODO: What to do if argument string not found? Currently adds a match with type name.
    String key = findKey(mutableKeyPosition, javaElement);
    if (key == null || isKeyDefined(key)) return;

    ICompilationUnit[] allCompilationUnits =
        JavaModelUtil.getAllCompilationUnits(new IJavaElement[] {javaElement});
    Object element = javaElement;
    if (allCompilationUnits != null && allCompilationUnits.length == 1)
      element = allCompilationUnits[0];

    fResult.addMatch(
        new Match(element, mutableKeyPosition.getOffset(), mutableKeyPosition.getLength()));
  }
  public void reportUnusedPropertyNames(IProgressMonitor pm) {
    // Don't use endReporting() for long running operation.
    pm.beginTask("", fProperties.size()); // $NON-NLS-1$
    boolean hasUnused = false;
    pm.setTaskName(NLSSearchMessages.NLSSearchResultRequestor_searching);
    FileEntry groupElement =
        new FileEntry(fPropertiesFile, NLSSearchMessages.NLSSearchResultCollector_unusedKeys);

    for (Enumeration<?> enumeration = fProperties.propertyNames();
        enumeration.hasMoreElements(); ) {
      String propertyName = (String) enumeration.nextElement();
      if (!fUsedPropertyNames.contains(propertyName)) {
        addMatch(groupElement, propertyName);
        hasUnused = true;
      }
      pm.worked(1);
    }
    if (hasUnused) fResult.addFileEntryGroup(groupElement);
    pm.done();
  }
 private void addMatch(FileEntry groupElement, String propertyName) {
   /*
    * TODO (bug 63794): Should read in .properties file with our own reader and not
    * with Properties.load(InputStream) . Then, we can remember start position and
    * original version (not interpreting escape characters) for each property.
    *
    * The current workaround is to escape the key again before searching in the
    * .properties file. However, this can fail if the key is escaped in a different
    * manner than what PropertyFileDocumentModel.unwindEscapeChars(.) produces.
    */
   String escapedPropertyName = PropertyFileDocumentModel.escape(propertyName, false);
   int start = findPropertyNameStartPosition(escapedPropertyName);
   int length;
   if (start == -1) { // not found -> report at beginning
     start = 0;
     length = 0;
   } else {
     length = escapedPropertyName.length();
   }
   fResult.addMatch(new Match(groupElement, start, length));
 }