public RerunAction(JComponent comp) {
   super(
       InspectionsBundle.message("inspection.action.rerun"),
       InspectionsBundle.message("inspection.action.rerun"),
       AllIcons.Actions.Rerun);
   registerCustomShortcutSet(CommonShortcuts.getRerun(), comp);
 }
Esempio n. 2
0
  public void showDescription(InspectionTool tool) {
    if (tool.getShortName().length() == 0) {
      showEmpty();
      return;
    }
    @NonNls StringBuffer page = new StringBuffer();
    page.append("<table border='0' cellspacing='0' cellpadding='0' width='100%'>");
    page.append("<tr><td colspan='2'>");
    HTMLComposer.appendHeading(
        page, InspectionsBundle.message("inspection.tool.in.browser.id.title"));
    page.append("</td></tr>");
    page.append("<tr><td width='37'></td>" + "<td>");
    page.append(tool.getShortName());
    page.append("</td></tr>");
    page.append("<tr height='10'></tr>");
    page.append("<tr><td colspan='2'>");
    HTMLComposer.appendHeading(
        page, InspectionsBundle.message("inspection.tool.in.browser.description.title"));
    page.append("</td></tr>");
    page.append("<tr><td width='37'></td>" + "<td>");
    @NonNls final String underConstruction = "<b>" + UNDER_CONSTRUCTION + "</b></html>";
    try {
      @NonNls String description = tool.loadDescription();
      if (description == null) {
        description = underConstruction;
      }
      page.append(UIUtil.getHtmlBody(description));

      page.append("</td></tr></table>");
      myHTMLViewer.setText(XmlStringUtil.wrapInHtml(page));
      setupStyle();
    } finally {
      myCurrentEntity = null;
    }
  }
    private OptionsPanel() {
      super(new GridBagLayout());

      GridBagConstraints gc = new GridBagConstraints();
      gc.fill = GridBagConstraints.HORIZONTAL;
      gc.weightx = 1;
      gc.weighty = 0;
      gc.anchor = GridBagConstraints.NORTHWEST;

      myPackageLocalForMembersCheckbox =
          new JCheckBox(InspectionsBundle.message("inspection.visibility.option"));
      myPackageLocalForMembersCheckbox.setSelected(SUGGEST_PACKAGE_LOCAL_FOR_MEMBERS);
      myPackageLocalForMembersCheckbox
          .getModel()
          .addChangeListener(
              new ChangeListener() {
                @Override
                public void stateChanged(ChangeEvent e) {
                  SUGGEST_PACKAGE_LOCAL_FOR_MEMBERS = myPackageLocalForMembersCheckbox.isSelected();
                }
              });

      gc.gridy = 0;
      add(myPackageLocalForMembersCheckbox, gc);

      myPackageLocalForTopClassesCheckbox =
          new JCheckBox(InspectionsBundle.message("inspection.visibility.option1"));
      myPackageLocalForTopClassesCheckbox.setSelected(SUGGEST_PACKAGE_LOCAL_FOR_TOP_CLASSES);
      myPackageLocalForTopClassesCheckbox
          .getModel()
          .addChangeListener(
              new ChangeListener() {
                @Override
                public void stateChanged(ChangeEvent e) {
                  SUGGEST_PACKAGE_LOCAL_FOR_TOP_CLASSES =
                      myPackageLocalForTopClassesCheckbox.isSelected();
                }
              });

      gc.gridy = 1;
      add(myPackageLocalForTopClassesCheckbox, gc);

      myPrivateForInnersCheckbox =
          new JCheckBox(InspectionsBundle.message("inspection.visibility.option2"));
      myPrivateForInnersCheckbox.setSelected(SUGGEST_PRIVATE_FOR_INNERS);
      myPrivateForInnersCheckbox
          .getModel()
          .addChangeListener(
              new ChangeListener() {
                @Override
                public void stateChanged(ChangeEvent e) {
                  SUGGEST_PRIVATE_FOR_INNERS = myPrivateForInnersCheckbox.isSelected();
                }
              });

      gc.gridy = 2;
      gc.weighty = 1;
      add(myPrivateForInnersCheckbox, gc);
    }
Esempio n. 4
0
    private OptionsPanel() {
      super(new GridBagLayout());

      GridBagConstraints gc = new GridBagConstraints();
      gc.weighty = 0;
      gc.weightx = 1;
      gc.fill = GridBagConstraints.HORIZONTAL;
      gc.anchor = GridBagConstraints.NORTHWEST;

      myReportClassesCheckbox =
          new JCheckBox(InspectionsBundle.message("inspection.can.be.final.option"));
      myReportClassesCheckbox.setSelected(REPORT_CLASSES);
      myReportClassesCheckbox
          .getModel()
          .addChangeListener(
              new ChangeListener() {
                @Override
                public void stateChanged(ChangeEvent e) {
                  REPORT_CLASSES = myReportClassesCheckbox.isSelected();
                }
              });
      gc.gridy = 0;
      add(myReportClassesCheckbox, gc);

      myReportMethodsCheckbox =
          new JCheckBox(InspectionsBundle.message("inspection.can.be.final.option1"));
      myReportMethodsCheckbox.setSelected(REPORT_METHODS);
      myReportMethodsCheckbox
          .getModel()
          .addChangeListener(
              new ChangeListener() {
                @Override
                public void stateChanged(ChangeEvent e) {
                  REPORT_METHODS = myReportMethodsCheckbox.isSelected();
                }
              });
      gc.gridy++;
      add(myReportMethodsCheckbox, gc);

      myReportFieldsCheckbox =
          new JCheckBox(InspectionsBundle.message("inspection.can.be.final.option2"));
      myReportFieldsCheckbox.setSelected(REPORT_FIELDS);
      myReportFieldsCheckbox
          .getModel()
          .addChangeListener(
              new ChangeListener() {
                @Override
                public void stateChanged(ChangeEvent e) {
                  REPORT_FIELDS = myReportFieldsCheckbox.isSelected();
                }
              });

      gc.weighty = 1;
      gc.gridy++;
      add(myReportFieldsCheckbox, gc);
    }
Esempio n. 5
0
  @Override
  @Nullable
  public CommonProblemDescriptor[] checkElement(
      @NotNull final RefEntity refEntity,
      @NotNull final AnalysisScope scope,
      @NotNull final InspectionManager manager,
      @NotNull final GlobalInspectionContext globalContext,
      @NotNull final ProblemDescriptionsProcessor processor) {
    if (refEntity instanceof RefJavaElement) {
      final RefJavaElement refElement = (RefJavaElement) refEntity;
      if (refElement instanceof RefParameter) return null;
      if (!refElement.isReferenced()) return null;
      if (refElement.isSyntheticJSP()) return null;
      if (refElement.isFinal()) return null;
      if (!((RefElementImpl) refElement).checkFlag(CanBeFinalAnnotator.CAN_BE_FINAL_MASK))
        return null;

      final PsiMember psiMember = (PsiMember) refElement.getElement();
      if (psiMember == null || !CanBeFinalHandler.allowToBeFinal(psiMember)) return null;

      PsiIdentifier psiIdentifier = null;
      if (refElement instanceof RefClass) {
        RefClass refClass = (RefClass) refElement;
        if (refClass.isInterface() || refClass.isAnonymous() || refClass.isAbstract()) return null;
        if (!isReportClasses()) return null;
        psiIdentifier = ((PsiClass) psiMember).getNameIdentifier();
      } else if (refElement instanceof RefMethod) {
        RefMethod refMethod = (RefMethod) refElement;
        if (refMethod.getOwnerClass().isFinal()) return null;
        if (!isReportMethods()) return null;
        psiIdentifier = ((PsiMethod) psiMember).getNameIdentifier();
      } else if (refElement instanceof RefField) {
        if (!isReportFields()) return null;
        psiIdentifier = ((PsiField) psiMember).getNameIdentifier();
      }

      if (psiIdentifier != null) {
        return new ProblemDescriptor[] {
          manager.createProblemDescriptor(
              psiIdentifier,
              InspectionsBundle.message("inspection.export.results.can.be.final.description"),
              new AcceptSuggested(globalContext.getRefManager()),
              ProblemHighlightType.GENERIC_ERROR_OR_WARNING,
              false)
        };
      }
    }
    return null;
  }
Esempio n. 6
0
 private void appendSuppressSection(final StringBuffer buf) {
   final InspectionTool tool = getTool();
   if (tool != null) {
     final HighlightDisplayKey key = HighlightDisplayKey.find(tool.getShortName());
     if (key != null) { // dummy entry points
       final SuppressActionWrapper.SuppressTreeAction[] suppressActions =
           new SuppressActionWrapper(
                   myView.getProject(), tool, myView.getTree().getSelectionPaths())
               .getChildren(null);
       if (suppressActions.length > 0) {
         final List<AnAction> activeSuppressActions = new ArrayList<AnAction>();
         for (SuppressActionWrapper.SuppressTreeAction suppressAction : suppressActions) {
           if (suppressAction.isAvailable()) {
             activeSuppressActions.add(suppressAction);
           }
         }
         if (!activeSuppressActions.isEmpty()) {
           int idx = 0;
           @NonNls final String br = "<br>";
           buf.append(br);
           HTMLComposerImpl.appendHeading(
               buf, InspectionsBundle.message("inspection.export.results.suppress"));
           for (AnAction suppressAction : activeSuppressActions) {
             buf.append(br);
             if (idx == activeSuppressActions.size() - 1) {
               buf.append(br);
             }
             HTMLComposer.appendAfterHeaderIndention(buf);
             @NonNls
             final String href =
                 "<a HREF=\"file://bred.txt#suppress:"
                     + idx
                     + "\">"
                     + suppressAction.getTemplatePresentation().getText()
                     + "</a>";
             buf.append(href);
             idx++;
           }
         }
       }
     }
   }
 }
 private EditSettingsAction() {
   super(
       InspectionsBundle.message("inspection.action.edit.settings"),
       InspectionsBundle.message("inspection.action.edit.settings"),
       AllIcons.General.Settings);
 }
  @SuppressWarnings({"NonStaticInitializer"})
  private JComponent createRightActionsToolbar() {
    myIncludeAction =
        new AnAction(InspectionsBundle.message("inspections.result.view.include.action.text")) {
          {
            registerCustomShortcutSet(CommonShortcuts.INSERT, myTree);
          }

          @Override
          public void actionPerformed(AnActionEvent e) {
            final TreePath[] paths = myTree.getSelectionPaths();
            if (paths != null) {
              for (TreePath path : paths) {
                ((InspectionTreeNode) path.getLastPathComponent()).amnesty();
              }
            }
            updateView(false);
          }

          @Override
          public void update(final AnActionEvent e) {
            final TreePath[] paths = myTree.getSelectionPaths();
            e.getPresentation()
                .setEnabled(
                    paths != null
                        && paths.length > 0
                        && !myGlobalInspectionContext.getUIOptions().FILTER_RESOLVED_ITEMS);
          }
        };

    myExcludeAction =
        new AnAction(InspectionsBundle.message("inspections.result.view.exclude.action.text")) {
          {
            registerCustomShortcutSet(CommonShortcuts.getDelete(), myTree);
          }

          @Override
          public void actionPerformed(final AnActionEvent e) {
            final TreePath[] paths = myTree.getSelectionPaths();
            if (paths != null) {
              for (TreePath path : paths) {
                ((InspectionTreeNode) path.getLastPathComponent()).ignoreElement();
              }
            }
            updateView(false);
          }

          @Override
          public void update(final AnActionEvent e) {
            final TreePath[] path = myTree.getSelectionPaths();
            e.getPresentation().setEnabled(path != null && path.length > 0);
          }
        };

    DefaultActionGroup specialGroup = new DefaultActionGroup();
    specialGroup.add(myGlobalInspectionContext.getUIOptions().createGroupBySeverityAction(this));
    specialGroup.add(myGlobalInspectionContext.getUIOptions().createGroupByDirectoryAction(this));
    specialGroup.add(
        myGlobalInspectionContext.getUIOptions().createFilterResolvedItemsAction(this));
    specialGroup.add(
        myGlobalInspectionContext.getUIOptions().createShowOutdatedProblemsAction(this));
    specialGroup.add(myGlobalInspectionContext.getUIOptions().createShowDiffOnlyAction(this));
    specialGroup.add(new EditSettingsAction());
    specialGroup.add(new InvokeQuickFixAction(this));
    specialGroup.add(new InspectionsOptionsToolbarAction(this));
    return createToolbar(specialGroup);
  }
Esempio n. 9
0
class Browser extends JPanel {
  private static final String UNDER_CONSTRUCTION =
      InspectionsBundle.message("inspection.tool.description.under.construction.text");
  private final List<ClickListener> myClickListeners =
      ContainerUtil.createLockFreeCopyOnWriteList();
  private RefEntity myCurrentEntity;
  private JEditorPane myHTMLViewer;
  private final InspectionResultsView myView;
  private final HyperlinkListener myHyperLinkListener;
  private CommonProblemDescriptor myCurrentDescriptor;

  public static class ClickEvent {
    public static final int REF_ELEMENT = 1;
    public static final int FILE_OFFSET = 2;
    private final VirtualFile myFile;
    private final int myStartPosition;
    private final int myEndPosition;
    private final RefElement refElement;
    private final int myEventType;

    public ClickEvent(VirtualFile myFile, int myStartPosition, int myEndPosition) {
      this.myFile = myFile;
      this.myStartPosition = myStartPosition;
      this.myEndPosition = myEndPosition;
      myEventType = FILE_OFFSET;
      refElement = null;
    }

    public int getEventType() {
      return myEventType;
    }

    public VirtualFile getFile() {
      return myFile;
    }

    public int getStartOffset() {
      return myStartPosition;
    }

    public int getEndOffset() {
      return myEndPosition;
    }

    public RefElement getClickedElement() {
      return refElement;
    }
  }

  public void dispose() {
    removeAll();
    if (myHTMLViewer != null) {
      myHTMLViewer.removeHyperlinkListener(myHyperLinkListener);
      myHTMLViewer = null;
    }
    myClickListeners.clear();
  }

  public interface ClickListener {
    void referenceClicked(ClickEvent e);
  }

  private void showPageFromHistory(RefEntity newEntity) {
    InspectionTool tool = getTool(newEntity);
    try {
      if (tool instanceof DescriptorProviderInspection
          && !(tool instanceof CommonInspectionToolWrapper)) {
        showEmpty();
      } else {
        try {
          String html = generateHTML(newEntity, tool);
          myHTMLViewer.read(new StringReader(html), null);
          setupStyle();
          myHTMLViewer.setCaretPosition(0);
        } catch (Exception e) {
          showEmpty();
        }
      }
    } finally {
      myCurrentEntity = newEntity;
      myCurrentDescriptor = null;
    }
  }

  public void showPageFor(RefEntity refEntity, CommonProblemDescriptor descriptor) {
    try {
      String html = generateHTML(refEntity, descriptor);
      myHTMLViewer.read(new StringReader(html), null);
      setupStyle();
      myHTMLViewer.setCaretPosition(0);
    } catch (Exception e) {
      showEmpty();
    } finally {
      myCurrentEntity = refEntity;
      myCurrentDescriptor = descriptor;
    }
  }

  public void showPageFor(RefEntity newEntity) {
    if (newEntity == null) {
      showEmpty();
      return;
    }
    // multiple problems for one entity -> refresh browser
    showPageFromHistory(newEntity.getRefManager().getRefinedElement(newEntity));
  }

  public Browser(InspectionResultsView view) {
    super(new BorderLayout());
    myView = view;

    myCurrentEntity = null;
    myCurrentDescriptor = null;

    myHTMLViewer =
        new JEditorPane(
            UIUtil.HTML_MIME,
            InspectionsBundle.message("inspection.offline.view.empty.browser.text"));
    myHTMLViewer.setEditable(false);
    myHyperLinkListener =
        new HyperlinkListener() {
          @Override
          public void hyperlinkUpdate(HyperlinkEvent e) {
            if (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) {
              JEditorPane pane = (JEditorPane) e.getSource();
              if (e instanceof HTMLFrameHyperlinkEvent) {
                HTMLFrameHyperlinkEvent evt = (HTMLFrameHyperlinkEvent) e;
                HTMLDocument doc = (HTMLDocument) pane.getDocument();
                doc.processHTMLFrameHyperlinkEvent(evt);
              } else {
                try {
                  URL url = e.getURL();
                  @NonNls String ref = url.getRef();
                  if (ref.startsWith("pos:")) {
                    int delimeterPos = ref.indexOf(':', "pos:".length() + 1);
                    String startPosition = ref.substring("pos:".length(), delimeterPos);
                    String endPosition = ref.substring(delimeterPos + 1);
                    Integer textStartOffset = new Integer(startPosition);
                    Integer textEndOffset = new Integer(endPosition);
                    String fileURL = url.toExternalForm();
                    fileURL = fileURL.substring(0, fileURL.indexOf('#'));
                    VirtualFile vFile = VirtualFileManager.getInstance().findFileByUrl(fileURL);
                    if (vFile != null) {
                      fireClickEvent(vFile, textStartOffset.intValue(), textEndOffset.intValue());
                    }
                  } else if (ref.startsWith("descr:")) {
                    if (myCurrentDescriptor instanceof ProblemDescriptor) {
                      PsiElement psiElement =
                          ((ProblemDescriptor) myCurrentDescriptor).getPsiElement();
                      if (psiElement == null) return;
                      VirtualFile vFile = psiElement.getContainingFile().getVirtualFile();
                      if (vFile != null) {
                        TextRange range =
                            ((ProblemDescriptorBase) myCurrentDescriptor).getTextRange();
                        fireClickEvent(vFile, range.getStartOffset(), range.getEndOffset());
                      }
                    }
                  } else if (ref.startsWith("invoke:")) {
                    int actionNumber = Integer.parseInt(ref.substring("invoke:".length()));
                    getTool()
                        .getQuickFixes(new RefElement[] {(RefElement) myCurrentEntity})[
                        actionNumber]
                        .doApplyFix(new RefElement[] {(RefElement) myCurrentEntity}, myView);
                  } else if (ref.startsWith("invokelocal:")) {
                    int actionNumber = Integer.parseInt(ref.substring("invokelocal:".length()));
                    if (actionNumber > -1) {
                      invokeLocalFix(actionNumber);
                    }
                  } else if (ref.startsWith("suppress:")) {
                    final SuppressActionWrapper.SuppressTreeAction[] suppressTreeActions =
                        new SuppressActionWrapper(
                                myView.getProject(),
                                getTool(),
                                myView.getTree().getSelectionPaths())
                            .getChildren(null);
                    final List<AnAction> activeActions = new ArrayList<AnAction>();
                    for (SuppressActionWrapper.SuppressTreeAction suppressTreeAction :
                        suppressTreeActions) {
                      if (suppressTreeAction.isAvailable()) activeActions.add(suppressTreeAction);
                    }
                    if (!activeActions.isEmpty()) {
                      int actionNumber = Integer.parseInt(ref.substring("suppress:".length()));
                      if (actionNumber > -1 && activeActions.size() > actionNumber) {
                        activeActions.get(actionNumber).actionPerformed(null);
                      }
                    }
                  } else {
                    int offset = Integer.parseInt(ref);
                    String fileURL = url.toExternalForm();
                    fileURL = fileURL.substring(0, fileURL.indexOf('#'));
                    VirtualFile vFile = VirtualFileManager.getInstance().findFileByUrl(fileURL);
                    if (vFile == null) {
                      vFile = VfsUtil.findFileByURL(url);
                    }
                    if (vFile != null) {
                      fireClickEvent(vFile, offset, offset);
                    }
                  }
                } catch (Throwable t) {
                  // ???
                }
              }
            }
          }
        };
    myHTMLViewer.addHyperlinkListener(myHyperLinkListener);

    final JScrollPane pane = ScrollPaneFactory.createScrollPane(myHTMLViewer);
    pane.setBorder(null);
    add(pane, BorderLayout.CENTER);
    setupStyle();
  }

  private void setupStyle() {
    Document document = myHTMLViewer.getDocument();
    if (!(document instanceof StyledDocument)) {
      return;
    }

    StyledDocument styledDocument = (StyledDocument) document;

    EditorColorsManager colorsManager = EditorColorsManager.getInstance();
    EditorColorsScheme scheme = colorsManager.getGlobalScheme();

    Style style = styledDocument.addStyle("active", null);
    StyleConstants.setFontFamily(style, scheme.getEditorFontName());
    StyleConstants.setFontSize(style, scheme.getEditorFontSize());
    styledDocument.setCharacterAttributes(0, document.getLength(), style, false);
  }

  public void addClickListener(ClickListener listener) {
    myClickListeners.add(listener);
  }

  private void fireClickEvent(VirtualFile file, int startPosition, int endPosition) {
    ClickEvent e = new ClickEvent(file, startPosition, endPosition);

    for (ClickListener listener : myClickListeners) {
      listener.referenceClicked(e);
    }
  }

  private String generateHTML(final RefEntity refEntity, final InspectionTool tool) {
    final StringBuffer buf = new StringBuffer();
    if (refEntity instanceof RefElement) {
      final Runnable action =
          new Runnable() {
            @Override
            public void run() {
              tool.getComposer().compose(buf, refEntity);
            }
          };
      ApplicationManager.getApplication().runReadAction(action);
    } else {
      tool.getComposer().compose(buf, refEntity);
    }

    uppercaseFirstLetter(buf);

    if (refEntity instanceof RefElement) {
      appendSuppressSection(buf);
    }

    insertHeaderFooter(buf);

    return buf.toString();
  }

  @SuppressWarnings({"HardCodedStringLiteral"})
  private static void insertHeaderFooter(final StringBuffer buf) {
    buf.insert(0, "<HTML><BODY>");
    buf.append("</BODY></HTML>");
  }

  private String generateHTML(final RefEntity refEntity, final CommonProblemDescriptor descriptor) {
    final StringBuffer buf = new StringBuffer();
    final Runnable action =
        new Runnable() {
          @Override
          public void run() {
            InspectionTool tool = getTool(refEntity);
            tool.getComposer().compose(buf, refEntity, descriptor);
          }
        };
    ApplicationManager.getApplication().runReadAction(action);

    uppercaseFirstLetter(buf);

    if (refEntity instanceof RefElement) {
      appendSuppressSection(buf);
    }

    insertHeaderFooter(buf);
    return buf.toString();
  }

  private InspectionTool getTool(final RefEntity refEntity) {
    InspectionTool tool = getTool();
    assert tool != null;
    final GlobalInspectionContextImpl manager = tool.getContext();
    if (manager == null) return tool;
    if (refEntity instanceof RefElement) {
      PsiElement element = ((RefElement) refEntity).getElement();
      if (element == null) return tool;
      final InspectionProfileWrapper profileWrapper =
          InspectionProjectProfileManagerImpl.getInstanceImpl(manager.getProject())
              .getProfileWrapper();
      if (profileWrapper == null) return tool;
      tool = profileWrapper.getInspectionTool(tool.getShortName(), element);
    }
    return tool;
  }

  private void appendSuppressSection(final StringBuffer buf) {
    final InspectionTool tool = getTool();
    if (tool != null) {
      final HighlightDisplayKey key = HighlightDisplayKey.find(tool.getShortName());
      if (key != null) { // dummy entry points
        final SuppressActionWrapper.SuppressTreeAction[] suppressActions =
            new SuppressActionWrapper(
                    myView.getProject(), tool, myView.getTree().getSelectionPaths())
                .getChildren(null);
        if (suppressActions.length > 0) {
          final List<AnAction> activeSuppressActions = new ArrayList<AnAction>();
          for (SuppressActionWrapper.SuppressTreeAction suppressAction : suppressActions) {
            if (suppressAction.isAvailable()) {
              activeSuppressActions.add(suppressAction);
            }
          }
          if (!activeSuppressActions.isEmpty()) {
            int idx = 0;
            @NonNls final String br = "<br>";
            buf.append(br);
            HTMLComposerImpl.appendHeading(
                buf, InspectionsBundle.message("inspection.export.results.suppress"));
            for (AnAction suppressAction : activeSuppressActions) {
              buf.append(br);
              if (idx == activeSuppressActions.size() - 1) {
                buf.append(br);
              }
              HTMLComposer.appendAfterHeaderIndention(buf);
              @NonNls
              final String href =
                  "<a HREF=\"file://bred.txt#suppress:"
                      + idx
                      + "\">"
                      + suppressAction.getTemplatePresentation().getText()
                      + "</a>";
              buf.append(href);
              idx++;
            }
          }
        }
      }
    }
  }

  private static void uppercaseFirstLetter(final StringBuffer buf) {
    if (buf.length() > 1) {
      char[] firstLetter = new char[1];
      buf.getChars(0, 1, firstLetter, 0);
      buf.setCharAt(0, Character.toUpperCase(firstLetter[0]));
    }
  }

  @SuppressWarnings({"HardCodedStringLiteral"})
  public void showEmpty() {
    myCurrentEntity = null;
    try {
      myHTMLViewer.read(new StringReader("<html><body></body></html>"), null);
    } catch (IOException e) {
      // can't be
    }
  }

  public void showDescription(InspectionTool tool) {
    if (tool.getShortName().length() == 0) {
      showEmpty();
      return;
    }
    @NonNls StringBuffer page = new StringBuffer();
    page.append("<table border='0' cellspacing='0' cellpadding='0' width='100%'>");
    page.append("<tr><td colspan='2'>");
    HTMLComposer.appendHeading(
        page, InspectionsBundle.message("inspection.tool.in.browser.id.title"));
    page.append("</td></tr>");
    page.append("<tr><td width='37'></td>" + "<td>");
    page.append(tool.getShortName());
    page.append("</td></tr>");
    page.append("<tr height='10'></tr>");
    page.append("<tr><td colspan='2'>");
    HTMLComposer.appendHeading(
        page, InspectionsBundle.message("inspection.tool.in.browser.description.title"));
    page.append("</td></tr>");
    page.append("<tr><td width='37'></td>" + "<td>");
    @NonNls final String underConstruction = "<b>" + UNDER_CONSTRUCTION + "</b></html>";
    try {
      @NonNls String description = tool.loadDescription();
      if (description == null) {
        description = underConstruction;
      }
      page.append(UIUtil.getHtmlBody(description));

      page.append("</td></tr></table>");
      myHTMLViewer.setText(XmlStringUtil.wrapInHtml(page));
      setupStyle();
    } finally {
      myCurrentEntity = null;
    }
  }

  @Nullable
  private InspectionTool getTool() {
    if (myView != null) {
      return myView.getTree().getSelectedTool();
    }
    return null;
  }

  public void invokeLocalFix(int idx) {
    if (myView.getTree().getSelectionCount() != 1) return;
    final InspectionTreeNode node =
        (InspectionTreeNode) myView.getTree().getSelectionPath().getLastPathComponent();
    if (node instanceof ProblemDescriptionNode) {
      final ProblemDescriptionNode problemNode = (ProblemDescriptionNode) node;
      final CommonProblemDescriptor descriptor = problemNode.getDescriptor();
      final RefEntity element = problemNode.getElement();
      invokeFix(element, descriptor, idx);
    } else if (node instanceof RefElementNode) {
      RefElementNode elementNode = (RefElementNode) node;
      RefEntity element = elementNode.getElement();
      CommonProblemDescriptor descriptor = elementNode.getProblem();
      if (descriptor != null) {
        invokeFix(element, descriptor, idx);
      }
    }
  }

  private void invokeFix(
      final RefEntity element, final CommonProblemDescriptor descriptor, final int idx) {
    final QuickFix[] fixes = descriptor.getFixes();
    if (fixes != null && fixes.length > idx && fixes[idx] != null) {
      if (element instanceof RefElement) {
        PsiElement psiElement = ((RefElement) element).getElement();
        if (psiElement != null && psiElement.isValid()) {
          if (!FileModificationService.getInstance().preparePsiElementForWrite(psiElement)) return;
          performFix(element, descriptor, idx, fixes[idx]);
        }
      } else {
        performFix(element, descriptor, idx, fixes[idx]);
      }
    }
  }

  private void performFix(
      final RefEntity element,
      final CommonProblemDescriptor descriptor,
      final int idx,
      final QuickFix fix) {
    final Runnable command =
        new Runnable() {
          @Override
          public void run() {
            ApplicationManager.getApplication()
                .runWriteAction(
                    new Runnable() {
                      @Override
                      public void run() {
                        final PsiModificationTracker tracker =
                            PsiManager.getInstance(myView.getProject()).getModificationTracker();
                        final long startCount = tracker.getModificationCount();
                        CommandProcessor.getInstance()
                            .markCurrentCommandAsGlobal(myView.getProject());
                        // CCE here means QuickFix was incorrectly inherited
                        fix.applyFix(myView.getProject(), descriptor);
                        if (startCount != tracker.getModificationCount()) {
                          final DescriptorProviderInspection tool =
                              ((DescriptorProviderInspection) myView.getTree().getSelectedTool());
                          if (tool != null) {
                            tool.ignoreProblem(element, descriptor, idx);
                          }
                          myView.updateView(false);
                        }
                      }
                    });
          }
        };
    CommandProcessor.getInstance()
        .executeCommand(myView.getProject(), command, fix.getName(), null);
  }
}
Esempio n. 10
0
  public Browser(InspectionResultsView view) {
    super(new BorderLayout());
    myView = view;

    myCurrentEntity = null;
    myCurrentDescriptor = null;

    myHTMLViewer =
        new JEditorPane(
            UIUtil.HTML_MIME,
            InspectionsBundle.message("inspection.offline.view.empty.browser.text"));
    myHTMLViewer.setEditable(false);
    myHyperLinkListener =
        new HyperlinkListener() {
          @Override
          public void hyperlinkUpdate(HyperlinkEvent e) {
            if (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) {
              JEditorPane pane = (JEditorPane) e.getSource();
              if (e instanceof HTMLFrameHyperlinkEvent) {
                HTMLFrameHyperlinkEvent evt = (HTMLFrameHyperlinkEvent) e;
                HTMLDocument doc = (HTMLDocument) pane.getDocument();
                doc.processHTMLFrameHyperlinkEvent(evt);
              } else {
                try {
                  URL url = e.getURL();
                  @NonNls String ref = url.getRef();
                  if (ref.startsWith("pos:")) {
                    int delimeterPos = ref.indexOf(':', "pos:".length() + 1);
                    String startPosition = ref.substring("pos:".length(), delimeterPos);
                    String endPosition = ref.substring(delimeterPos + 1);
                    Integer textStartOffset = new Integer(startPosition);
                    Integer textEndOffset = new Integer(endPosition);
                    String fileURL = url.toExternalForm();
                    fileURL = fileURL.substring(0, fileURL.indexOf('#'));
                    VirtualFile vFile = VirtualFileManager.getInstance().findFileByUrl(fileURL);
                    if (vFile != null) {
                      fireClickEvent(vFile, textStartOffset.intValue(), textEndOffset.intValue());
                    }
                  } else if (ref.startsWith("descr:")) {
                    if (myCurrentDescriptor instanceof ProblemDescriptor) {
                      PsiElement psiElement =
                          ((ProblemDescriptor) myCurrentDescriptor).getPsiElement();
                      if (psiElement == null) return;
                      VirtualFile vFile = psiElement.getContainingFile().getVirtualFile();
                      if (vFile != null) {
                        TextRange range =
                            ((ProblemDescriptorBase) myCurrentDescriptor).getTextRange();
                        fireClickEvent(vFile, range.getStartOffset(), range.getEndOffset());
                      }
                    }
                  } else if (ref.startsWith("invoke:")) {
                    int actionNumber = Integer.parseInt(ref.substring("invoke:".length()));
                    getTool()
                        .getQuickFixes(new RefElement[] {(RefElement) myCurrentEntity})[
                        actionNumber]
                        .doApplyFix(new RefElement[] {(RefElement) myCurrentEntity}, myView);
                  } else if (ref.startsWith("invokelocal:")) {
                    int actionNumber = Integer.parseInt(ref.substring("invokelocal:".length()));
                    if (actionNumber > -1) {
                      invokeLocalFix(actionNumber);
                    }
                  } else if (ref.startsWith("suppress:")) {
                    final SuppressActionWrapper.SuppressTreeAction[] suppressTreeActions =
                        new SuppressActionWrapper(
                                myView.getProject(),
                                getTool(),
                                myView.getTree().getSelectionPaths())
                            .getChildren(null);
                    final List<AnAction> activeActions = new ArrayList<AnAction>();
                    for (SuppressActionWrapper.SuppressTreeAction suppressTreeAction :
                        suppressTreeActions) {
                      if (suppressTreeAction.isAvailable()) activeActions.add(suppressTreeAction);
                    }
                    if (!activeActions.isEmpty()) {
                      int actionNumber = Integer.parseInt(ref.substring("suppress:".length()));
                      if (actionNumber > -1 && activeActions.size() > actionNumber) {
                        activeActions.get(actionNumber).actionPerformed(null);
                      }
                    }
                  } else {
                    int offset = Integer.parseInt(ref);
                    String fileURL = url.toExternalForm();
                    fileURL = fileURL.substring(0, fileURL.indexOf('#'));
                    VirtualFile vFile = VirtualFileManager.getInstance().findFileByUrl(fileURL);
                    if (vFile == null) {
                      vFile = VfsUtil.findFileByURL(url);
                    }
                    if (vFile != null) {
                      fireClickEvent(vFile, offset, offset);
                    }
                  }
                } catch (Throwable t) {
                  // ???
                }
              }
            }
          }
        };
    myHTMLViewer.addHyperlinkListener(myHyperLinkListener);

    final JScrollPane pane = ScrollPaneFactory.createScrollPane(myHTMLViewer);
    pane.setBorder(null);
    add(pane, BorderLayout.CENTER);
    setupStyle();
  }
Esempio n. 11
0
public class CanBeFinalInspection extends GlobalJavaBatchInspectionTool {
  private static final Logger LOG =
      Logger.getInstance("#com.intellij.codeInspection.canBeFinal.CanBeFinalInspection");

  public boolean REPORT_CLASSES;
  public boolean REPORT_METHODS;
  public boolean REPORT_FIELDS = true;
  public static final String DISPLAY_NAME =
      InspectionsBundle.message("inspection.can.be.final.display.name");
  @NonNls public static final String SHORT_NAME = "CanBeFinal";

  @NonNls
  private static final String QUICK_FIX_NAME =
      InspectionsBundle.message("inspection.can.be.final.accept.quickfix");

  private class OptionsPanel extends JPanel {
    private final JCheckBox myReportClassesCheckbox;
    private final JCheckBox myReportMethodsCheckbox;
    private final JCheckBox myReportFieldsCheckbox;

    private OptionsPanel() {
      super(new GridBagLayout());

      GridBagConstraints gc = new GridBagConstraints();
      gc.weighty = 0;
      gc.weightx = 1;
      gc.fill = GridBagConstraints.HORIZONTAL;
      gc.anchor = GridBagConstraints.NORTHWEST;

      myReportClassesCheckbox =
          new JCheckBox(InspectionsBundle.message("inspection.can.be.final.option"));
      myReportClassesCheckbox.setSelected(REPORT_CLASSES);
      myReportClassesCheckbox
          .getModel()
          .addChangeListener(
              new ChangeListener() {
                @Override
                public void stateChanged(ChangeEvent e) {
                  REPORT_CLASSES = myReportClassesCheckbox.isSelected();
                }
              });
      gc.gridy = 0;
      add(myReportClassesCheckbox, gc);

      myReportMethodsCheckbox =
          new JCheckBox(InspectionsBundle.message("inspection.can.be.final.option1"));
      myReportMethodsCheckbox.setSelected(REPORT_METHODS);
      myReportMethodsCheckbox
          .getModel()
          .addChangeListener(
              new ChangeListener() {
                @Override
                public void stateChanged(ChangeEvent e) {
                  REPORT_METHODS = myReportMethodsCheckbox.isSelected();
                }
              });
      gc.gridy++;
      add(myReportMethodsCheckbox, gc);

      myReportFieldsCheckbox =
          new JCheckBox(InspectionsBundle.message("inspection.can.be.final.option2"));
      myReportFieldsCheckbox.setSelected(REPORT_FIELDS);
      myReportFieldsCheckbox
          .getModel()
          .addChangeListener(
              new ChangeListener() {
                @Override
                public void stateChanged(ChangeEvent e) {
                  REPORT_FIELDS = myReportFieldsCheckbox.isSelected();
                }
              });

      gc.weighty = 1;
      gc.gridy++;
      add(myReportFieldsCheckbox, gc);
    }
  }

  public boolean isReportClasses() {
    return REPORT_CLASSES;
  }

  public boolean isReportMethods() {
    return REPORT_METHODS;
  }

  public boolean isReportFields() {
    return REPORT_FIELDS;
  }

  @Override
  public JComponent createOptionsPanel() {
    return new OptionsPanel();
  }

  @Override
  @Nullable
  public RefGraphAnnotator getAnnotator(@NotNull final RefManager refManager) {
    return new CanBeFinalAnnotator(refManager);
  }

  @Override
  @Nullable
  public CommonProblemDescriptor[] checkElement(
      @NotNull final RefEntity refEntity,
      @NotNull final AnalysisScope scope,
      @NotNull final InspectionManager manager,
      @NotNull final GlobalInspectionContext globalContext,
      @NotNull final ProblemDescriptionsProcessor processor) {
    if (refEntity instanceof RefJavaElement) {
      final RefJavaElement refElement = (RefJavaElement) refEntity;
      if (refElement instanceof RefParameter) return null;
      if (!refElement.isReferenced()) return null;
      if (refElement.isSyntheticJSP()) return null;
      if (refElement.isFinal()) return null;
      if (!((RefElementImpl) refElement).checkFlag(CanBeFinalAnnotator.CAN_BE_FINAL_MASK))
        return null;

      final PsiMember psiMember = (PsiMember) refElement.getElement();
      if (psiMember == null || !CanBeFinalHandler.allowToBeFinal(psiMember)) return null;

      PsiIdentifier psiIdentifier = null;
      if (refElement instanceof RefClass) {
        RefClass refClass = (RefClass) refElement;
        if (refClass.isInterface() || refClass.isAnonymous() || refClass.isAbstract()) return null;
        if (!isReportClasses()) return null;
        psiIdentifier = ((PsiClass) psiMember).getNameIdentifier();
      } else if (refElement instanceof RefMethod) {
        RefMethod refMethod = (RefMethod) refElement;
        if (refMethod.getOwnerClass().isFinal()) return null;
        if (!isReportMethods()) return null;
        psiIdentifier = ((PsiMethod) psiMember).getNameIdentifier();
      } else if (refElement instanceof RefField) {
        if (!isReportFields()) return null;
        psiIdentifier = ((PsiField) psiMember).getNameIdentifier();
      }

      if (psiIdentifier != null) {
        return new ProblemDescriptor[] {
          manager.createProblemDescriptor(
              psiIdentifier,
              InspectionsBundle.message("inspection.export.results.can.be.final.description"),
              new AcceptSuggested(globalContext.getRefManager()),
              ProblemHighlightType.GENERIC_ERROR_OR_WARNING,
              false)
        };
      }
    }
    return null;
  }

  @Override
  protected boolean queryExternalUsagesRequests(
      @NotNull final RefManager manager,
      @NotNull final GlobalJavaInspectionContext globalContext,
      @NotNull final ProblemDescriptionsProcessor problemsProcessor) {
    for (RefElement entryPoint : globalContext.getEntryPointsManager(manager).getEntryPoints()) {
      problemsProcessor.ignoreElement(entryPoint);
    }

    manager.iterate(
        new RefJavaVisitor() {
          @Override
          public void visitElement(@NotNull RefEntity refEntity) {
            if (problemsProcessor.getDescriptions(refEntity) == null) return;
            refEntity.accept(
                new RefJavaVisitor() {
                  @Override
                  public void visitMethod(@NotNull final RefMethod refMethod) {
                    if (!refMethod.isStatic()
                        && !PsiModifier.PRIVATE.equals(refMethod.getAccessModifier())
                        && !(refMethod instanceof RefImplicitConstructor)) {
                      globalContext.enqueueDerivedMethodsProcessor(
                          refMethod,
                          new GlobalJavaInspectionContext.DerivedMethodsProcessor() {
                            @Override
                            public boolean process(PsiMethod derivedMethod) {
                              ((RefElementImpl) refMethod)
                                  .setFlag(false, CanBeFinalAnnotator.CAN_BE_FINAL_MASK);
                              problemsProcessor.ignoreElement(refMethod);
                              return false;
                            }
                          });
                    }
                  }

                  @Override
                  public void visitClass(@NotNull final RefClass refClass) {
                    if (!refClass.isAnonymous()) {
                      globalContext.enqueueDerivedClassesProcessor(
                          refClass,
                          new GlobalJavaInspectionContext.DerivedClassesProcessor() {
                            @Override
                            public boolean process(PsiClass inheritor) {
                              ((RefClassImpl) refClass)
                                  .setFlag(false, CanBeFinalAnnotator.CAN_BE_FINAL_MASK);
                              problemsProcessor.ignoreElement(refClass);
                              return false;
                            }
                          });
                    }
                  }

                  @Override
                  public void visitField(@NotNull final RefField refField) {
                    globalContext.enqueueFieldUsagesProcessor(
                        refField,
                        new GlobalJavaInspectionContext.UsagesProcessor() {
                          @Override
                          public boolean process(PsiReference psiReference) {
                            PsiElement expression = psiReference.getElement();
                            if (expression instanceof PsiReferenceExpression
                                && PsiUtil.isAccessedForWriting((PsiExpression) expression)) {
                              ((RefFieldImpl) refField)
                                  .setFlag(false, CanBeFinalAnnotator.CAN_BE_FINAL_MASK);
                              problemsProcessor.ignoreElement(refField);
                              return false;
                            }
                            return true;
                          }
                        });
                  }
                });
          }
        });

    return false;
  }

  @Override
  @Nullable
  public QuickFix getQuickFix(final String hint) {
    return new AcceptSuggested(null);
  }

  @Override
  @NotNull
  public String getDisplayName() {
    return DISPLAY_NAME;
  }

  @Override
  @NotNull
  public String getGroupDisplayName() {
    return GroupNames.DECLARATION_REDUNDANCY;
  }

  @Override
  @NotNull
  public String getShortName() {
    return SHORT_NAME;
  }

  private static class AcceptSuggested implements LocalQuickFix {
    private final RefManager myManager;

    public AcceptSuggested(final RefManager manager) {
      myManager = manager;
    }

    @Override
    @NotNull
    public String getFamilyName() {
      return QUICK_FIX_NAME;
    }

    @Override
    public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
      final PsiElement element = descriptor.getPsiElement();
      final PsiModifierListOwner psiElement =
          PsiTreeUtil.getParentOfType(element, PsiModifierListOwner.class);
      if (psiElement != null) {
        RefJavaElement refElement =
            (RefJavaElement) (myManager != null ? myManager.getReference(psiElement) : null);
        try {
          if (psiElement instanceof PsiVariable) {
            ((PsiVariable) psiElement).normalizeDeclaration();
          }
          final PsiModifierList modifierList = psiElement.getModifierList();
          LOG.assertTrue(modifierList != null);
          modifierList.setModifierProperty(PsiModifier.FINAL, true);
          modifierList.setModifierProperty(PsiModifier.VOLATILE, false);
        } catch (IncorrectOperationException e) {
          LOG.error(e);
        }

        if (refElement != null) {
          RefJavaUtil.getInstance().setIsFinal(refElement, true);
        }
      }
    }
  }
}
 @Override
 @NotNull
 public String getName() {
   return InspectionsBundle.message("inspection.visibility.accept.quickfix");
 }
public class VisibilityInspection extends GlobalJavaInspectionTool {
  private static final Logger LOG =
      Logger.getInstance("#com.intellij.codeInspection.visibility.VisibilityInspection");
  public boolean SUGGEST_PACKAGE_LOCAL_FOR_MEMBERS = true;
  public boolean SUGGEST_PACKAGE_LOCAL_FOR_TOP_CLASSES = true;
  public boolean SUGGEST_PRIVATE_FOR_INNERS = false;
  private static final String DISPLAY_NAME =
      InspectionsBundle.message("inspection.visibility.display.name");
  @NonNls private static final String SHORT_NAME = "WeakerAccess";
  private static final String CAN_BE_PRIVATE =
      InspectionsBundle.message("inspection.visibility.compose.suggestion", "private");
  private static final String CAN_BE_PACKAGE_LOCAL =
      InspectionsBundle.message("inspection.visibility.compose.suggestion", "package local");
  private static final String CAN_BE_PROTECTED =
      InspectionsBundle.message("inspection.visibility.compose.suggestion", "protected");

  private class OptionsPanel extends JPanel {
    private final JCheckBox myPackageLocalForMembersCheckbox;
    private final JCheckBox myPrivateForInnersCheckbox;
    private final JCheckBox myPackageLocalForTopClassesCheckbox;

    private OptionsPanel() {
      super(new GridBagLayout());

      GridBagConstraints gc = new GridBagConstraints();
      gc.fill = GridBagConstraints.HORIZONTAL;
      gc.weightx = 1;
      gc.weighty = 0;
      gc.anchor = GridBagConstraints.NORTHWEST;

      myPackageLocalForMembersCheckbox =
          new JCheckBox(InspectionsBundle.message("inspection.visibility.option"));
      myPackageLocalForMembersCheckbox.setSelected(SUGGEST_PACKAGE_LOCAL_FOR_MEMBERS);
      myPackageLocalForMembersCheckbox
          .getModel()
          .addChangeListener(
              new ChangeListener() {
                @Override
                public void stateChanged(ChangeEvent e) {
                  SUGGEST_PACKAGE_LOCAL_FOR_MEMBERS = myPackageLocalForMembersCheckbox.isSelected();
                }
              });

      gc.gridy = 0;
      add(myPackageLocalForMembersCheckbox, gc);

      myPackageLocalForTopClassesCheckbox =
          new JCheckBox(InspectionsBundle.message("inspection.visibility.option1"));
      myPackageLocalForTopClassesCheckbox.setSelected(SUGGEST_PACKAGE_LOCAL_FOR_TOP_CLASSES);
      myPackageLocalForTopClassesCheckbox
          .getModel()
          .addChangeListener(
              new ChangeListener() {
                @Override
                public void stateChanged(ChangeEvent e) {
                  SUGGEST_PACKAGE_LOCAL_FOR_TOP_CLASSES =
                      myPackageLocalForTopClassesCheckbox.isSelected();
                }
              });

      gc.gridy = 1;
      add(myPackageLocalForTopClassesCheckbox, gc);

      myPrivateForInnersCheckbox =
          new JCheckBox(InspectionsBundle.message("inspection.visibility.option2"));
      myPrivateForInnersCheckbox.setSelected(SUGGEST_PRIVATE_FOR_INNERS);
      myPrivateForInnersCheckbox
          .getModel()
          .addChangeListener(
              new ChangeListener() {
                @Override
                public void stateChanged(ChangeEvent e) {
                  SUGGEST_PRIVATE_FOR_INNERS = myPrivateForInnersCheckbox.isSelected();
                }
              });

      gc.gridy = 2;
      gc.weighty = 1;
      add(myPrivateForInnersCheckbox, gc);
    }
  }

  @Override
  public JComponent createOptionsPanel() {
    return new OptionsPanel();
  }

  @Override
  @NotNull
  public String getDisplayName() {
    return DISPLAY_NAME;
  }

  @Override
  @NotNull
  public String getGroupDisplayName() {
    return GroupNames.DECLARATION_REDUNDANCY;
  }

  @Override
  @NotNull
  public String getShortName() {
    return SHORT_NAME;
  }

  @Override
  @Nullable
  public CommonProblemDescriptor[] checkElement(
      @NotNull final RefEntity refEntity,
      @NotNull final AnalysisScope scope,
      @NotNull final InspectionManager manager,
      @NotNull final GlobalInspectionContext globalContext,
      @NotNull final ProblemDescriptionsProcessor processor) {
    if (refEntity instanceof RefJavaElement) {
      final RefJavaElement refElement = (RefJavaElement) refEntity;

      if (refElement instanceof RefParameter) return null;
      if (refElement.isSyntheticJSP()) return null;

      // ignore entry points.
      if (refElement.isEntry()) return null;

      // ignore implicit constructors. User should not be able to see them.
      if (refElement instanceof RefImplicitConstructor) return null;

      if (refElement instanceof RefField
          && ((RefField) refElement).getElement() instanceof PsiEnumConstant) return null;

      // ignore library override methods.
      if (refElement instanceof RefMethod) {
        RefMethod refMethod = (RefMethod) refElement;
        if (refMethod.isExternalOverride()) return null;
        if (refMethod.isEntry()) return null;
      }

      // ignore anonymous classes. They do not have access modifiers.
      if (refElement instanceof RefClass) {
        RefClass refClass = (RefClass) refElement;
        if (refClass.isAnonymous()
            || refClass.isEntry()
            || refClass.isTestCase()
            || refClass.isServlet()
            || refClass.isApplet()
            || refClass.isLocalClass()) return null;
        if (isTopLevelClass(refClass) && !SUGGEST_PACKAGE_LOCAL_FOR_TOP_CLASSES) return null;
      }

      // ignore unreferenced code. They could be a potential entry points.
      if (refElement.getInReferences().isEmpty()) return null;

      // ignore interface members. They always have public access modifier.
      if (refElement.getOwner() instanceof RefClass) {
        RefClass refClass = (RefClass) refElement.getOwner();
        if (refClass.isInterface()) return null;
      }
      String access = getPossibleAccess(refElement);
      if (access != refElement.getAccessModifier() && access != null) {
        final PsiElement element = refElement.getElement();
        final PsiElement nameIdentifier =
            element != null ? HighlightUsagesHandler.getNameIdentifier(element) : null;
        if (nameIdentifier != null) {
          return new ProblemDescriptor[] {
            manager.createProblemDescriptor(
                nameIdentifier,
                access.equals(PsiModifier.PRIVATE)
                    ? CAN_BE_PRIVATE
                    : access.equals(PsiModifier.PACKAGE_LOCAL)
                        ? CAN_BE_PACKAGE_LOCAL
                        : CAN_BE_PROTECTED,
                new AcceptSuggestedAccess(globalContext.getRefManager(), access),
                ProblemHighlightType.GENERIC_ERROR_OR_WARNING,
                false)
          };
        }
      }
    }
    return null;
  }

  @Nullable
  @PsiModifier.ModifierConstant
  public String getPossibleAccess(@Nullable RefJavaElement refElement) {
    if (refElement == null) return null;
    String curAccess = refElement.getAccessModifier();
    String weakestAccess = PsiModifier.PRIVATE;

    if (isTopLevelClass(refElement) || isCalledOnSubClasses(refElement)) {
      weakestAccess = PsiModifier.PACKAGE_LOCAL;
    }

    if (isAbstractMethod(refElement)) {
      weakestAccess = PsiModifier.PROTECTED;
    }

    if (curAccess == weakestAccess) return curAccess;

    while (true) {
      String weakerAccess = getWeakerAccess(curAccess, refElement);
      if (weakerAccess == null
          || RefJavaUtil.getInstance().compareAccess(weakerAccess, weakestAccess) < 0) break;
      if (isAccessible(refElement, weakerAccess)) {
        curAccess = weakerAccess;
      } else {
        break;
      }
    }

    return curAccess;
  }

  private static boolean isCalledOnSubClasses(RefElement refElement) {
    return refElement instanceof RefMethod && ((RefMethod) refElement).isCalledOnSubClass();
  }

  private static boolean isAbstractMethod(RefElement refElement) {
    return refElement instanceof RefMethod && ((RefMethod) refElement).isAbstract();
  }

  private static boolean isTopLevelClass(RefElement refElement) {
    return refElement instanceof RefClass
        && RefJavaUtil.getInstance().getTopLevelClass(refElement) == refElement;
  }

  @Nullable
  @PsiModifier.ModifierConstant
  private String getWeakerAccess(
      @PsiModifier.ModifierConstant String curAccess, RefElement refElement) {
    if (curAccess == PsiModifier.PUBLIC) {
      return isTopLevelClass(refElement) ? PsiModifier.PACKAGE_LOCAL : PsiModifier.PROTECTED;
    }
    if (curAccess == PsiModifier.PROTECTED) {
      return SUGGEST_PACKAGE_LOCAL_FOR_MEMBERS ? PsiModifier.PACKAGE_LOCAL : PsiModifier.PRIVATE;
    }
    if (curAccess == PsiModifier.PACKAGE_LOCAL) {
      return PsiModifier.PRIVATE;
    }

    return null;
  }

  private boolean isAccessible(
      RefJavaElement to, @PsiModifier.ModifierConstant String accessModifier) {

    for (RefElement refElement : to.getInReferences()) {
      if (!isAccessibleFrom(refElement, to, accessModifier)) return false;
    }

    if (to instanceof RefMethod) {
      RefMethod refMethod = (RefMethod) to;

      if (refMethod.isAbstract()
          && (refMethod.getDerivedMethods().isEmpty()
              || refMethod.getAccessModifier() == PsiModifier.PRIVATE)) return false;

      for (RefMethod refOverride : refMethod.getDerivedMethods()) {
        if (!isAccessibleFrom(refOverride, to, accessModifier)) return false;
      }

      for (RefMethod refSuper : refMethod.getSuperMethods()) {
        if (RefJavaUtil.getInstance().compareAccess(refSuper.getAccessModifier(), accessModifier)
            > 0) return false;
      }
    }

    if (to instanceof RefClass) {
      RefClass refClass = (RefClass) to;
      for (RefClass subClass : refClass.getSubClasses()) {
        if (!isAccessibleFrom(subClass, to, accessModifier)) return false;
      }

      List children = refClass.getChildren();
      if (children != null) {
        for (Object refElement : children) {
          if (!isAccessible((RefJavaElement) refElement, accessModifier)) return false;
        }
      }

      for (final RefElement refElement : refClass.getInTypeReferences()) {
        if (!isAccessibleFrom(refElement, refClass, accessModifier)) return false;
      }

      List<RefJavaElement> classExporters = ((RefClassImpl) refClass).getClassExporters();
      if (classExporters != null) {
        for (RefJavaElement refExporter : classExporters) {
          if (getAccessLevel(accessModifier) < getAccessLevel(refExporter.getAccessModifier()))
            return false;
        }
      }
    }

    return true;
  }

  private static int getAccessLevel(@PsiModifier.ModifierConstant String access) {
    if (access == PsiModifier.PRIVATE) return 1;
    if (access == PsiModifier.PACKAGE_LOCAL) return 2;
    if (access == PsiModifier.PROTECTED) return 3;
    return 4;
  }

  private boolean isAccessibleFrom(RefElement from, RefJavaElement to, String accessModifier) {
    if (accessModifier == PsiModifier.PUBLIC) return true;

    final RefJavaUtil refUtil = RefJavaUtil.getInstance();
    if (accessModifier == PsiModifier.PACKAGE_LOCAL) {
      return RefJavaUtil.getPackage(from) == RefJavaUtil.getPackage(to);
    }

    RefClass fromTopLevel = refUtil.getTopLevelClass(from);
    RefClass toTopLevel = refUtil.getTopLevelClass(to);
    RefClass fromOwner = refUtil.getOwnerClass(from);
    RefClass toOwner = refUtil.getOwnerClass(to);

    if (accessModifier == PsiModifier.PROTECTED) {
      if (SUGGEST_PRIVATE_FOR_INNERS) {
        return refUtil.isInheritor(fromTopLevel, toOwner)
            || fromOwner != null && refUtil.isInheritor(fromOwner, toTopLevel)
            || toOwner != null && refUtil.getOwnerClass(toOwner) == from;
      }

      return refUtil.isInheritor(fromTopLevel, toOwner);
    }

    if (accessModifier == PsiModifier.PRIVATE) {
      if (SUGGEST_PRIVATE_FOR_INNERS) {
        if (isInExtendsList(to, fromTopLevel.getElement().getExtendsList())) return false;
        if (isInExtendsList(to, fromTopLevel.getElement().getImplementsList())) return false;
        if (isInAnnotations(to, fromTopLevel)) return false;
        return fromTopLevel == toOwner
            || fromOwner == toTopLevel
            || toOwner != null && refUtil.getOwnerClass(toOwner) == from;
      }

      if (fromOwner != null
          && fromOwner.isStatic()
          && !to.isStatic()
          && refUtil.isInheritor(fromOwner, toOwner)) return false;

      if (fromTopLevel == toOwner) {
        if (from instanceof RefClass && to instanceof RefClass) {
          final PsiClass fromClass = ((RefClass) from).getElement();
          LOG.assertTrue(fromClass != null);
          if (isInExtendsList(to, fromClass.getExtendsList())) return false;
          if (isInExtendsList(to, fromClass.getImplementsList())) return false;
        }

        return true;
      }
    }

    return false;
  }

  private static boolean isInAnnotations(final RefJavaElement to, final RefClass fromTopLevel) {
    final PsiModifierList modifierList = fromTopLevel.getElement().getModifierList();
    if (modifierList == null) return false;
    final PsiElement toElement = to.getElement();

    final boolean[] resolved = new boolean[] {false};
    modifierList.accept(
        new JavaRecursiveElementWalkingVisitor() {
          @Override
          public void visitReferenceExpression(PsiReferenceExpression expression) {
            if (resolved[0]) return;
            super.visitReferenceExpression(expression);
            if (expression.resolve() == toElement) {
              resolved[0] = true;
            }
          }
        });
    return resolved[0];
  }

  private static boolean isInExtendsList(
      final RefJavaElement to, final PsiReferenceList extendsList) {
    if (extendsList != null) {
      final PsiJavaCodeReferenceElement[] referenceElements = extendsList.getReferenceElements();
      for (PsiJavaCodeReferenceElement referenceElement : referenceElements) {
        final PsiReferenceParameterList parameterList = referenceElement.getParameterList();
        if (parameterList != null) {
          for (PsiType type : parameterList.getTypeArguments()) {
            if (extendsList
                .getManager()
                .areElementsEquivalent(PsiUtil.resolveClassInType(type), to.getElement())) {
              return true;
            }
          }
        }
      }
    }
    return false;
  }

  @Override
  protected boolean queryExternalUsagesRequests(
      @NotNull final RefManager manager,
      @NotNull final GlobalJavaInspectionContext globalContext,
      @NotNull final ProblemDescriptionsProcessor processor) {
    final EntryPointsManager entryPointsManager = globalContext.getEntryPointsManager(manager);
    for (RefElement entryPoint : entryPointsManager.getEntryPoints()) {
      ignoreElement(processor, entryPoint);
    }

    ExtensionPoint<VisibilityExtension> point =
        Extensions.getRootArea().getExtensionPoint(ExtensionPoints.VISIBLITY_TOOL);
    for (VisibilityExtension addin : point.getExtensions()) {
      addin.fillIgnoreList(manager, processor);
    }
    manager.iterate(
        new RefJavaVisitor() {
          @Override
          public void visitElement(@NotNull final RefEntity refEntity) {
            if (!(refEntity instanceof RefElement)) return;
            if (processor.getDescriptions(refEntity) == null) return;
            refEntity.accept(
                new RefJavaVisitor() {
                  @Override
                  public void visitField(@NotNull final RefField refField) {
                    if (refField.getAccessModifier() != PsiModifier.PRIVATE) {
                      globalContext.enqueueFieldUsagesProcessor(
                          refField,
                          new GlobalJavaInspectionContext.UsagesProcessor() {
                            @Override
                            public boolean process(PsiReference psiReference) {
                              ignoreElement(processor, refField);
                              return false;
                            }
                          });
                    }
                  }

                  @Override
                  public void visitMethod(@NotNull final RefMethod refMethod) {
                    if (!refMethod.isExternalOverride()
                        && refMethod.getAccessModifier() != PsiModifier.PRIVATE
                        && !(refMethod instanceof RefImplicitConstructor)) {
                      globalContext.enqueueDerivedMethodsProcessor(
                          refMethod,
                          new GlobalJavaInspectionContext.DerivedMethodsProcessor() {
                            @Override
                            public boolean process(PsiMethod derivedMethod) {
                              ignoreElement(processor, refMethod);
                              return false;
                            }
                          });

                      globalContext.enqueueMethodUsagesProcessor(
                          refMethod,
                          new GlobalJavaInspectionContext.UsagesProcessor() {
                            @Override
                            public boolean process(PsiReference psiReference) {
                              ignoreElement(processor, refMethod);
                              return false;
                            }
                          });

                      if (entryPointsManager.isAddNonJavaEntries()) {
                        final RefClass ownerClass = refMethod.getOwnerClass();
                        if (refMethod.isConstructor()
                            && ownerClass.getDefaultConstructor() != null) {
                          String qualifiedName = ownerClass.getElement().getQualifiedName();
                          if (qualifiedName != null) {
                            final Project project = manager.getProject();
                            PsiSearchHelper.SERVICE
                                .getInstance(project)
                                .processUsagesInNonJavaFiles(
                                    qualifiedName,
                                    new PsiNonJavaFileReferenceProcessor() {
                                      @Override
                                      public boolean process(
                                          PsiFile file, int startOffset, int endOffset) {
                                        entryPointsManager.addEntryPoint(refMethod, false);
                                        ignoreElement(processor, refMethod);
                                        return false;
                                      }
                                    },
                                    GlobalSearchScope.projectScope(project));
                          }
                        }
                      }
                    }
                  }

                  @Override
                  public void visitClass(@NotNull final RefClass refClass) {
                    if (!refClass.isAnonymous()) {
                      globalContext.enqueueDerivedClassesProcessor(
                          refClass,
                          new GlobalJavaInspectionContext.DerivedClassesProcessor() {
                            @Override
                            public boolean process(PsiClass inheritor) {
                              ignoreElement(processor, refClass);
                              return false;
                            }
                          });

                      globalContext.enqueueClassUsagesProcessor(
                          refClass,
                          new GlobalJavaInspectionContext.UsagesProcessor() {
                            @Override
                            public boolean process(PsiReference psiReference) {
                              ignoreElement(processor, refClass);
                              return false;
                            }
                          });
                    }
                  }
                });
          }
        });
    return false;
  }

  private static void ignoreElement(
      @NotNull ProblemDescriptionsProcessor processor, @NotNull RefEntity refElement) {
    processor.ignoreElement(refElement);

    if (refElement instanceof RefClass) {
      RefClass refClass = (RefClass) refElement;
      RefMethod defaultConstructor = refClass.getDefaultConstructor();
      if (defaultConstructor != null) {
        processor.ignoreElement(defaultConstructor);
        return;
      }
    }

    RefEntity owner = refElement.getOwner();
    if (owner instanceof RefElement) {
      processor.ignoreElement(owner);
    }
  }

  @Override
  public void compose(
      @NotNull final StringBuffer buf,
      @NotNull final RefEntity refEntity,
      @NotNull final HTMLComposer composer) {
    composer.appendElementInReferences(buf, (RefElement) refEntity);
  }

  @Override
  @Nullable
  public QuickFix getQuickFix(final String hint) {
    return new AcceptSuggestedAccess(null, hint);
  }

  @Override
  @Nullable
  public String getHint(@NotNull final QuickFix fix) {
    return ((AcceptSuggestedAccess) fix).getHint();
  }

  private static class AcceptSuggestedAccess implements LocalQuickFix {
    private final RefManager myManager;
    @PsiModifier.ModifierConstant private final String myHint;

    private AcceptSuggestedAccess(
        final RefManager manager, @PsiModifier.ModifierConstant String hint) {
      myManager = manager;
      myHint = hint;
    }

    @Override
    @NotNull
    public String getName() {
      return InspectionsBundle.message("inspection.visibility.accept.quickfix");
    }

    @Override
    @NotNull
    public String getFamilyName() {
      return getName();
    }

    @Override
    public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
      if (!FileModificationService.getInstance()
          .preparePsiElementForWrite(descriptor.getPsiElement())) return;
      final PsiModifierListOwner element =
          PsiTreeUtil.getParentOfType(descriptor.getPsiElement(), PsiModifierListOwner.class);
      if (element != null) {
        RefElement refElement = null;
        if (myManager != null) {
          refElement = myManager.getReference(element);
        }
        try {
          if (element instanceof PsiVariable) {
            ((PsiVariable) element).normalizeDeclaration();
          }

          PsiModifierList list = element.getModifierList();

          LOG.assertTrue(list != null);

          if (element instanceof PsiMethod) {
            PsiMethod psiMethod = (PsiMethod) element;
            PsiClass containingClass = psiMethod.getContainingClass();
            if (containingClass != null
                && containingClass.getParent() instanceof PsiFile
                && myHint == PsiModifier.PRIVATE
                && list.hasModifierProperty(PsiModifier.FINAL)) {
              list.setModifierProperty(PsiModifier.FINAL, false);
            }
          }

          list.setModifierProperty(myHint, true);
          if (refElement instanceof RefJavaElement) {
            RefJavaUtil.getInstance().setAccessModifier((RefJavaElement) refElement, myHint);
          }
        } catch (IncorrectOperationException e) {
          LOG.error(e);
        }
      }
    }

    public String getHint() {
      return myHint;
    }
  }
}
 @NotNull
 public String getName() {
   // The test (see the TestThisPlugin class) uses this string to identify the quick fix action.
   return InspectionsBundle.message("inspection.comparing.references.use.quickfix");
 }
/** @author max */
public class ComparingReferencesInspection extends BaseJavaLocalInspectionTool {
  private static final Logger LOG =
      Logger.getInstance("#com.intellij.codeInspection.ComparingReferencesInspection");

  private final LocalQuickFix myQuickFix = new MyQuickFix();

  @SuppressWarnings({"WeakerAccess"})
  @NonNls
  public String CHECKED_CLASSES = "java.lang.String;java.util.Date";

  @NonNls
  private static final String DESCRIPTION_TEMPLATE =
      InspectionsBundle.message("inspection.comparing.references.problem.descriptor");

  @NotNull
  public String getDisplayName() {

    return "'==' or '!=' instead of 'equals()'";
  }

  @NotNull
  public String getGroupDisplayName() {
    return GroupNames.BUGS_GROUP_NAME;
  }

  @NotNull
  public String getShortName() {
    return "ComparingReferences";
  }

  private boolean isCheckedType(PsiType type) {
    if (!(type instanceof PsiClassType)) return false;

    StringTokenizer tokenizer = new StringTokenizer(CHECKED_CLASSES, ";");
    while (tokenizer.hasMoreTokens()) {
      String className = tokenizer.nextToken();
      if (type.equalsToText(className)) return true;
    }

    return false;
  }

  @NotNull
  @Override
  public PsiElementVisitor buildVisitor(@NotNull final ProblemsHolder holder, boolean isOnTheFly) {
    return new JavaElementVisitor() {

      @Override
      public void visitReferenceExpression(PsiReferenceExpression psiReferenceExpression) {}

      @Override
      public void visitBinaryExpression(PsiBinaryExpression expression) {
        super.visitBinaryExpression(expression);
        IElementType opSign = expression.getOperationSign().getTokenType();
        if (opSign == JavaTokenType.EQEQ || opSign == JavaTokenType.NE) {
          PsiExpression lOperand = expression.getLOperand();
          PsiExpression rOperand = expression.getROperand();
          if (rOperand == null || isNullLiteral(lOperand) || isNullLiteral(rOperand)) return;

          PsiType lType = lOperand.getType();
          PsiType rType = rOperand.getType();

          if (isCheckedType(lType) || isCheckedType(rType)) {
            holder.registerProblem(expression, DESCRIPTION_TEMPLATE, myQuickFix);
          }
        }
      }
    };
  }

  private static boolean isNullLiteral(PsiExpression expr) {
    return expr instanceof PsiLiteralExpression && "null".equals(expr.getText());
  }

  private static class MyQuickFix implements LocalQuickFix {
    @NotNull
    public String getName() {
      // The test (see the TestThisPlugin class) uses this string to identify the quick fix action.
      return InspectionsBundle.message("inspection.comparing.references.use.quickfix");
    }

    public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
      try {
        PsiBinaryExpression binaryExpression = (PsiBinaryExpression) descriptor.getPsiElement();
        IElementType opSign = binaryExpression.getOperationSign().getTokenType();
        PsiExpression lExpr = binaryExpression.getLOperand();
        PsiExpression rExpr = binaryExpression.getROperand();
        if (rExpr == null) return;

        PsiElementFactory factory = JavaPsiFacade.getInstance(project).getElementFactory();
        PsiMethodCallExpression equalsCall =
            (PsiMethodCallExpression) factory.createExpressionFromText("a.equals(b)", null);

        equalsCall.getMethodExpression().getQualifierExpression().replace(lExpr);
        equalsCall.getArgumentList().getExpressions()[0].replace(rExpr);

        PsiExpression result = (PsiExpression) binaryExpression.replace(equalsCall);

        if (opSign == JavaTokenType.NE) {
          PsiPrefixExpression negation =
              (PsiPrefixExpression) factory.createExpressionFromText("!a", null);
          negation.getOperand().replace(result);
          result.replace(negation);
        }
      } catch (IncorrectOperationException e) {
        LOG.error(e);
      }
    }

    @NotNull
    public String getFamilyName() {
      return getName();
    }
  }

  public JComponent createOptionsPanel() {
    JPanel panel = new JPanel(new FlowLayout(FlowLayout.LEFT));
    final JTextField checkedClasses = new JTextField(CHECKED_CLASSES);
    checkedClasses
        .getDocument()
        .addDocumentListener(
            new DocumentAdapter() {
              public void textChanged(DocumentEvent event) {
                CHECKED_CLASSES = checkedClasses.getText();
              }
            });

    panel.add(checkedClasses);
    return panel;
  }

  public boolean isEnabledByDefault() {
    return true;
  }
}
    private OptionsPanel() {
      super(new GridBagLayout());

      GridBagConstraints gc = new GridBagConstraints();
      gc.weighty = 0;
      gc.weightx = 1;
      gc.fill = GridBagConstraints.HORIZONTAL;
      gc.anchor = GridBagConstraints.NORTHWEST;

      mySuggestNullables =
          new JCheckBox(InspectionsBundle.message("inspection.data.flow.nullable.quickfix.option"));
      mySuggestNullables.setSelected(SUGGEST_NULLABLE_ANNOTATIONS);
      mySuggestNullables
          .getModel()
          .addChangeListener(
              new ChangeListener() {
                @Override
                public void stateChanged(ChangeEvent e) {
                  SUGGEST_NULLABLE_ANNOTATIONS = mySuggestNullables.isSelected();
                }
              });

      myDontReportTrueAsserts =
          new JCheckBox(InspectionsBundle.message("inspection.data.flow.true.asserts.option"));
      myDontReportTrueAsserts.setSelected(DONT_REPORT_TRUE_ASSERT_STATEMENTS);
      myDontReportTrueAsserts
          .getModel()
          .addChangeListener(
              new ChangeListener() {
                @Override
                public void stateChanged(ChangeEvent e) {
                  DONT_REPORT_TRUE_ASSERT_STATEMENTS = myDontReportTrueAsserts.isSelected();
                }
              });

      myIgnoreAssertions = new JCheckBox("Ignore assert statements");
      myIgnoreAssertions.setSelected(IGNORE_ASSERT_STATEMENTS);
      myIgnoreAssertions
          .getModel()
          .addChangeListener(
              new ChangeListener() {
                @Override
                public void stateChanged(ChangeEvent e) {
                  IGNORE_ASSERT_STATEMENTS = myIgnoreAssertions.isSelected();
                }
              });

      myReportConstantReferences =
          new JCheckBox("Warn when reading a value guaranteed to be constant");
      myReportConstantReferences.setSelected(REPORT_CONSTANT_REFERENCE_VALUES);
      myReportConstantReferences
          .getModel()
          .addChangeListener(
              new ChangeListener() {
                @Override
                public void stateChanged(ChangeEvent e) {
                  REPORT_CONSTANT_REFERENCE_VALUES = myReportConstantReferences.isSelected();
                }
              });

      myTreatUnknownMembersAsNullable =
          new JCheckBox("Treat non-annotated members and parameters as @Nullable");
      myTreatUnknownMembersAsNullable.setSelected(TREAT_UNKNOWN_MEMBERS_AS_NULLABLE);
      myTreatUnknownMembersAsNullable
          .getModel()
          .addChangeListener(
              new ChangeListener() {
                @Override
                public void stateChanged(ChangeEvent e) {
                  TREAT_UNKNOWN_MEMBERS_AS_NULLABLE = myTreatUnknownMembersAsNullable.isSelected();
                }
              });

      gc.insets = new Insets(0, 0, 0, 0);
      gc.gridy = 0;
      add(mySuggestNullables, gc);

      final JButton configureAnnotations =
          new JButton(InspectionsBundle.message("configure.annotations.option"));
      configureAnnotations.addActionListener(
          new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
              Project project =
                  CommonDataKeys.PROJECT.getData(
                      DataManager.getInstance().getDataContext(OptionsPanel.this));
              if (project == null) project = ProjectManager.getInstance().getDefaultProject();
              final NullableNotNullDialog dialog = new NullableNotNullDialog(project);
              dialog.show();
            }
          });
      gc.gridy++;
      gc.fill = GridBagConstraints.NONE;
      gc.insets.left = 20;
      gc.insets.bottom = 15;
      add(configureAnnotations, gc);

      gc.fill = GridBagConstraints.HORIZONTAL;
      gc.weighty = 1;
      gc.insets.left = 0;
      gc.gridy++;
      add(myDontReportTrueAsserts, gc);

      gc.gridy++;
      add(myIgnoreAssertions, gc);

      gc.gridy++;
      add(myReportConstantReferences, gc);

      gc.gridy++;
      add(myTreatUnknownMembersAsNullable, gc);
    }