private void informUserModal(CompletionProposalComputerDescriptor descriptor, IStatus status) {
    String title = DartTextMessages.CompletionProposalComputerRegistry_error_dialog_title;
    CompletionProposalCategory category = descriptor.getCategory();
    IContributor culprit = descriptor.getContributor();
    Set affectedPlugins = getAffectedContributors(category, culprit);

    final String avoidHint;
    final String culpritName = culprit == null ? null : culprit.getName();
    if (affectedPlugins.isEmpty()) {
      avoidHint =
          Messages.format(
              DartTextMessages.CompletionProposalComputerRegistry_messageAvoidanceHint,
              new Object[] {culpritName, category.getDisplayName()});
    } else {
      avoidHint =
          Messages.format(
              DartTextMessages.CompletionProposalComputerRegistry_messageAvoidanceHintWithWarning,
              new Object[] {culpritName, category.getDisplayName(), toString(affectedPlugins)});
    }

    String message = status.getMessage();
    // inlined from MessageDialog.openError
    MessageDialog dialog =
        new MessageDialog(
            DartToolsPlugin.getActiveWorkbenchShell(),
            title,
            null /* default image */,
            message,
            MessageDialog.ERROR,
            new String[] {IDialogConstants.OK_LABEL},
            0) {
          @Override
          protected Control createCustomArea(Composite parent) {
            Link link = new Link(parent, SWT.NONE);
            link.setText(avoidHint);
            link.addSelectionListener(
                new SelectionAdapter() {
                  @Override
                  public void widgetSelected(SelectionEvent e) {
                    PreferencesUtil.createPreferenceDialogOn(
                            getShell(),
                            "com.google.dart.tools.ui.internal.preferences.CodeAssistPreferenceAdvanced",
                            null,
                            null)
                        .open(); //$NON-NLS-1$
                  }
                });
            GridData gridData = new GridData(SWT.FILL, SWT.BEGINNING, true, false);
            gridData.widthHint = this.getMinimumMessageWidth();
            link.setLayoutData(gridData);
            return link;
          }
        };
    dialog.open();
  }
 /**
  * Returns the names of contributors affected by disabling a category.
  *
  * @param category the category that would be disabled
  * @param culprit the culprit plug-in, which is not included in the returned list
  * @return the names of the contributors other than <code>culprit</code> that contribute to <code>
  *     category</code> (element type: {@link String})
  */
 private Set getAffectedContributors(CompletionProposalCategory category, IContributor culprit) {
   Set affectedPlugins = new HashSet();
   for (Iterator it = getProposalComputerDescriptors().iterator(); it.hasNext(); ) {
     CompletionProposalComputerDescriptor desc = (CompletionProposalComputerDescriptor) it.next();
     CompletionProposalCategory cat = desc.getCategory();
     if (cat.equals(category)) {
       IContributor contributor = desc.getContributor();
       if (contributor != null && !culprit.equals(contributor)) {
         affectedPlugins.add(contributor.getName());
       }
     }
   }
   return affectedPlugins;
 }
  /**
   * Reloads the extensions to the extension point.
   *
   * <p>This method can be called more than once in order to reload from a changed extension
   * registry.
   */
  public void reload() {
    IExtensionRegistry registry = Platform.getExtensionRegistry();
    List elements =
        new ArrayList(
            Arrays.asList(
                registry.getConfigurationElementsFor(
                    DartToolsPlugin.getPluginId(), EXTENSION_POINT)));

    Map map = new HashMap();
    List all = new ArrayList();

    List categories = getCategories(elements);
    for (Iterator iter = elements.iterator(); iter.hasNext(); ) {
      IConfigurationElement element = (IConfigurationElement) iter.next();
      try {
        CompletionProposalComputerDescriptor desc =
            new CompletionProposalComputerDescriptor(element, this, categories);
        Set partitions = desc.getPartitions();
        for (Iterator it = partitions.iterator(); it.hasNext(); ) {
          String partition = (String) it.next();
          List list = (List) map.get(partition);
          if (list == null) {
            list = new ArrayList();
            map.put(partition, list);
          }
          list.add(desc);
        }
        all.add(desc);

      } catch (InvalidRegistryObjectException x) {
        /*
         * Element is not valid any longer as the contributing plug-in was unloaded or for some
         * other reason. Do not include the extension in the list and inform the user about it.
         */
        Object[] args = {element.toString()};
        String message =
            Messages.format(
                DartTextMessages.CompletionProposalComputerRegistry_invalid_message, args);
        IStatus status =
            new Status(IStatus.WARNING, DartToolsPlugin.getPluginId(), IStatus.OK, message, x);
        informUser(status);
      }
    }

    synchronized (this) {
      fCategories.clear();
      fCategories.addAll(categories);

      Set partitions = map.keySet();
      fDescriptorsByPartition.keySet().retainAll(partitions);
      fPublicDescriptorsByPartition.keySet().retainAll(partitions);
      for (Iterator it = partitions.iterator(); it.hasNext(); ) {
        String partition = (String) it.next();
        List old = (List) fDescriptorsByPartition.get(partition);
        List current = (List) map.get(partition);
        if (old != null) {
          old.clear();
          old.addAll(current);
        } else {
          fDescriptorsByPartition.put(partition, current);
          fPublicDescriptorsByPartition.put(partition, Collections.unmodifiableList(current));
        }
      }

      fDescriptors.clear();
      fDescriptors.addAll(all);
    }
  }